Due to convention, interfaces should not have TikTok name inside, but they should have prefix Live instead

- rename TikTokMapper to LiveMapper
- rename TikTokLiveMapperHelper to LiveMapperHelper

Create interface:
LiveEventsHandler for TikTokLiveEventHandler
LiveMessagesHandler for TikTokLiveMessageHandler
This commit is contained in:
jacek.wolniewicz
2024-07-01 22:19:07 +02:00
parent 85d99ce4f1
commit 1736236ccf
23 changed files with 140 additions and 226 deletions

View File

@@ -0,0 +1,19 @@
package io.github.jwdeveloper.tiktok.live;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
import java.util.HashSet;
import java.util.Optional;
public interface LiveEventsHandler {
void publish(LiveClient tikTokLiveClient, TikTokEvent tikTokEvent);
<T extends TikTokEvent> void subscribe(Class<?> clazz, EventConsumer<T> event);
<T extends TikTokEvent> void unsubscribeAll(Class<?> clazz);
<T extends TikTokEvent> void unsubscribe(EventConsumer<T> consumer);
<T extends TikTokEvent> void unsubscribe(Class<?> clazz, EventConsumer<T> consumer);
}

View File

@@ -0,0 +1,18 @@
package io.github.jwdeveloper.tiktok.live;
import io.github.jwdeveloper.tiktok.data.dto.MessageMetaData;
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketMessageEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandledMessageEvent;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import io.github.jwdeveloper.tiktok.utils.Stopwatch;
import java.time.Duration;
public interface LiveMessagesHandler {
void handle(LiveClient client, WebcastResponse webcastResponse);
void handleSingleMessage(LiveClient client, WebcastResponse.Message message);
}

View File

@@ -26,7 +26,7 @@ import io.github.jwdeveloper.dependance.implementation.DependanceContainerBuilde
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener; import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.mappers.TikTokMapper; import io.github.jwdeveloper.tiktok.mappers.LiveMapper;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -42,7 +42,7 @@ public interface LiveClientBuilder extends EventsBuilder<LiveClientBuilder> {
* @param onCustomMappings lambda method * @param onCustomMappings lambda method
* @return * @return
*/ */
LiveClientBuilder onMapping(Consumer<TikTokMapper> onCustomMappings); LiveClientBuilder onMapping(Consumer<LiveMapper> onCustomMappings);
/** /**

View File

@@ -27,9 +27,10 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction; import io.github.jwdeveloper.tiktok.mappers.data.MappingAction;
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult; import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
import java.util.List;
import java.util.function.Function; import java.util.function.Function;
public interface TikTokMapper { public interface LiveMapper {
/** /**
* when mapper is not found for messageName, TikTokLiveException is thrown * when mapper is not found for messageName, TikTokLiveException is thrown
@@ -40,7 +41,6 @@ public interface TikTokMapper {
TikTokMapperModel forMessage(String messageName); TikTokMapperModel forMessage(String messageName);
/** /**
*
* @param mapperName protocol buffer class type * @param mapperName protocol buffer class type
* @return * @return
*/ */
@@ -54,10 +54,9 @@ public interface TikTokMapper {
TikTokMapperModel forAnyMessage(); TikTokMapperModel forAnyMessage();
List<TikTokEvent> handleMapping(String messageName, byte[] bytes);
boolean isRegistered(String mapperName); boolean isRegistered(String mapperName);
<T extends GeneratedMessageV3> boolean isRegistered(Class<T> mapperName); <T extends GeneratedMessageV3> boolean isRegistered(Class<T> mapperName);
} }

View File

@@ -26,7 +26,7 @@ import com.google.protobuf.GeneratedMessageV3;
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException; import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
import io.github.jwdeveloper.tiktok.utils.ProtoBufferObject; import io.github.jwdeveloper.tiktok.utils.ProtoBufferObject;
public interface TikTokMapperHelper { public interface LiveMapperHelper {
/** /**
* @param bytes protocol buffer data bytes * @param bytes protocol buffer data bytes

View File

@@ -22,7 +22,7 @@
*/ */
package io.github.jwdeveloper.tiktok.mappers.data; package io.github.jwdeveloper.tiktok.mappers.data;
import io.github.jwdeveloper.tiktok.mappers.TikTokMapperHelper; import io.github.jwdeveloper.tiktok.mappers.LiveMapperHelper;
@FunctionalInterface @FunctionalInterface
public interface MappingAction<T> { public interface MappingAction<T> {
@@ -33,6 +33,6 @@ public interface MappingAction<T> {
* @param mapperHelper utils and helper methods that can be use to debbug/display/deserialize protocol buffer data * @param mapperHelper utils and helper methods that can be use to debbug/display/deserialize protocol buffer data
* @return * @return
*/ */
T onMapping(byte[] inputBytes, String messageName, TikTokMapperHelper mapperHelper); T onMapping(byte[] inputBytes, String messageName, LiveMapperHelper mapperHelper);
} }

View File

@@ -23,7 +23,6 @@
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import io.github.jwdeveloper.dependance.injector.api.annotations.Inject;
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.*; import io.github.jwdeveloper.tiktok.data.events.control.*;
@@ -38,22 +37,24 @@ import io.github.jwdeveloper.tiktok.live.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import io.github.jwdeveloper.tiktok.models.ConnectionState; import io.github.jwdeveloper.tiktok.models.ConnectionState;
import io.github.jwdeveloper.tiktok.websocket.SocketClient; import io.github.jwdeveloper.tiktok.websocket.SocketClient;
import lombok.Getter;
import java.util.Base64; import java.util.Base64;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.logging.Logger; import java.util.logging.Logger;
@Getter
public class TikTokLiveClient implements LiveClient public class TikTokLiveClient implements LiveClient
{ {
private final TikTokRoomInfo liveRoomInfo; private final TikTokRoomInfo roomInfo;
private final LiveHttpClient httpClient; private final LiveHttpClient httpClient;
private final SocketClient webSocketClient; private final SocketClient webSocketClient;
private final TikTokLiveEventHandler tikTokEventHandler; private final LiveEventsHandler tikTokEventHandler;
private final LiveClientSettings clientSettings; private final LiveClientSettings clientSettings;
private final ListenersManager listenersManager; private final ListenersManager listenersManager;
private final Logger logger; private final Logger logger;
private final GiftsManager giftsManager; private final GiftsManager giftManager;
private final TikTokLiveMessageHandler messageHandler; private final TikTokLiveMessageHandler messageHandler;
public TikTokLiveClient( public TikTokLiveClient(
@@ -67,8 +68,8 @@ public class TikTokLiveClient implements LiveClient
ListenersManager listenersManager, ListenersManager listenersManager,
Logger logger) { Logger logger) {
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
this.giftsManager = giftsManager; this.giftManager = giftsManager;
this.liveRoomInfo = tikTokLiveMeta; this.roomInfo = tikTokLiveMeta;
this.httpClient = tiktokHttpClient; this.httpClient = tiktokHttpClient;
this.webSocketClient = webSocketClient; this.webSocketClient = webSocketClient;
this.tikTokEventHandler = tikTokEventHandler; this.tikTokEventHandler = tikTokEventHandler;
@@ -119,45 +120,45 @@ public class TikTokLiveClient implements LiveClient
} }
public void tryConnect() { public void tryConnect() {
if (!liveRoomInfo.hasConnectionState(ConnectionState.DISCONNECTED)) { if (!roomInfo.hasConnectionState(ConnectionState.DISCONNECTED)) {
throw new TikTokLiveException("Already connected"); throw new TikTokLiveException("Already connected");
} }
setState(ConnectionState.CONNECTING); setState(ConnectionState.CONNECTING);
tikTokEventHandler.publish(this, new TikTokConnectingEvent()); tikTokEventHandler.publish(this, new TikTokConnectingEvent());
var userDataRequest = new LiveUserData.Request(liveRoomInfo.getHostName()); var userDataRequest = new LiveUserData.Request(roomInfo.getHostName());
var userData = httpClient.fetchLiveUserData(userDataRequest); var userData = httpClient.fetchLiveUserData(userDataRequest);
liveRoomInfo.setStartTime(userData.getStartTime()); roomInfo.setStartTime(userData.getStartTime());
liveRoomInfo.setRoomId(userData.getRoomId()); roomInfo.setRoomId(userData.getRoomId());
if (clientSettings.isFetchGifts()) if (clientSettings.isFetchGifts())
giftsManager.attachGiftsList(httpClient.fetchRoomGiftsData(userData.getRoomId()).getGifts()); giftManager.attachGiftsList(httpClient.fetchRoomGiftsData(userData.getRoomId()).getGifts());
if (userData.getUserStatus() == LiveUserData.UserStatus.Offline) if (userData.getUserStatus() == LiveUserData.UserStatus.Offline)
throw new TikTokLiveOfflineHostException("User is offline: " + liveRoomInfo.getHostName()); throw new TikTokLiveOfflineHostException("User is offline: " + roomInfo.getHostName());
if (userData.getUserStatus() == LiveUserData.UserStatus.NotFound) if (userData.getUserStatus() == LiveUserData.UserStatus.NotFound)
throw new TikTokLiveOfflineHostException("User not found: " + liveRoomInfo.getHostName()); throw new TikTokLiveOfflineHostException("User not found: " + roomInfo.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.isAgeRestricted() && clientSettings.isThrowOnAgeRestriction()) if (liveData.isAgeRestricted() && clientSettings.isThrowOnAgeRestriction())
throw new TikTokLiveException("Livestream for " + liveRoomInfo.getHostName() + " is 18+ or age restricted!"); throw new TikTokLiveException("Livestream for " + roomInfo.getHostName() + " is 18+ or age restricted!");
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostNotFound) if (liveData.getLiveStatus() == LiveData.LiveStatus.HostNotFound)
throw new TikTokLiveOfflineHostException("LiveStream for " + liveRoomInfo.getHostName() + " could not be found."); throw new TikTokLiveOfflineHostException("LiveStream for " + roomInfo.getHostName() + " could not be found.");
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostOffline) if (liveData.getLiveStatus() == LiveData.LiveStatus.HostOffline)
throw new TikTokLiveOfflineHostException("LiveStream for " + liveRoomInfo.getHostName() + " not found, is the Host offline?"); throw new TikTokLiveOfflineHostException("LiveStream for " + roomInfo.getHostName() + " not found, is the Host offline?");
tikTokEventHandler.publish(this, new TikTokRoomDataResponseEvent(liveData)); tikTokEventHandler.publish(this, new TikTokRoomDataResponseEvent(liveData));
liveRoomInfo.setTitle(liveData.getTitle()); roomInfo.setTitle(liveData.getTitle());
liveRoomInfo.setViewersCount(liveData.getViewers()); roomInfo.setViewersCount(liveData.getViewers());
liveRoomInfo.setTotalViewersCount(liveData.getTotalViewers()); roomInfo.setTotalViewersCount(liveData.getTotalViewers());
liveRoomInfo.setAgeRestricted(liveData.isAgeRestricted()); roomInfo.setAgeRestricted(liveData.isAgeRestricted());
liveRoomInfo.setHost(liveData.getHost()); roomInfo.setHost(liveData.getHost());
var preconnectEvent = new TikTokPreConnectionEvent(userData, liveData); var preconnectEvent = new TikTokPreConnectionEvent(userData, liveData);
tikTokEventHandler.publish(this, preconnectEvent); tikTokEventHandler.publish(this, preconnectEvent);
@@ -169,11 +170,11 @@ public class TikTokLiveClient implements LiveClient
webSocketClient.start(liveConnectionData, this); webSocketClient.start(liveConnectionData, this);
setState(ConnectionState.CONNECTED); setState(ConnectionState.CONNECTED);
tikTokEventHandler.publish(this, new TikTokRoomInfoEvent(liveRoomInfo)); tikTokEventHandler.publish(this, new TikTokRoomInfoEvent(roomInfo));
} }
public void disconnect() { public void disconnect() {
if (liveRoomInfo.hasConnectionState(ConnectionState.DISCONNECTED)) { if (roomInfo.hasConnectionState(ConnectionState.DISCONNECTED)) {
return; return;
} }
setState(ConnectionState.DISCONNECTED); setState(ConnectionState.DISCONNECTED);
@@ -182,7 +183,7 @@ public class TikTokLiveClient implements LiveClient
private void setState(ConnectionState connectionState) { private void setState(ConnectionState connectionState) {
logger.info("TikTokLive client state: " + connectionState.name()); logger.info("TikTokLive client state: " + connectionState.name());
liveRoomInfo.setConnectionState(connectionState); roomInfo.setConnectionState(connectionState);
} }
public void publishEvent(TikTokEvent event) { public void publishEvent(TikTokEvent event) {
@@ -203,22 +204,4 @@ public class TikTokLiveClient implements LiveClient
messageHandler.handleSingleMessage(this, message); messageHandler.handleSingleMessage(this, message);
} }
@Override
public GiftsManager getGiftManager() {
return giftsManager;
}
public LiveRoomInfo getRoomInfo() {
return liveRoomInfo;
}
@Override
public ListenersManager getListenersManager() {
return listenersManager;
}
@Override
public Logger getLogger() {
return logger;
}
} }

View File

@@ -27,17 +27,7 @@ import io.github.jwdeveloper.dependance.api.DependanceContainer;
import io.github.jwdeveloper.dependance.implementation.DependanceContainerBuilder; import io.github.jwdeveloper.dependance.implementation.DependanceContainerBuilder;
import io.github.jwdeveloper.tiktok.mappers.MessagesMapperFactory; import io.github.jwdeveloper.tiktok.mappers.MessagesMapperFactory;
import io.github.jwdeveloper.tiktok.common.LoggerFactory; import io.github.jwdeveloper.tiktok.common.LoggerFactory;
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.gift.*;
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
import io.github.jwdeveloper.tiktok.data.events.link.*;
import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEvent;
import io.github.jwdeveloper.tiktok.data.events.room.*;
import io.github.jwdeveloper.tiktok.data.events.social.*;
import io.github.jwdeveloper.tiktok.data.events.websocket.*;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftsManager; import io.github.jwdeveloper.tiktok.gifts.TikTokGiftsManager;
@@ -61,9 +51,9 @@ import java.util.logging.Logger;
public class TikTokLiveClientBuilder implements LiveClientBuilder { public class TikTokLiveClientBuilder implements LiveClientBuilder {
protected final LiveClientSettings clientSettings; protected final LiveClientSettings clientSettings;
protected final TikTokLiveEventHandler eventHandler; protected final LiveEventsHandler eventHandler;
protected final List<TikTokEventListener> listeners; protected final List<TikTokEventListener> listeners;
protected final List<Consumer<TikTokMapper>> onCustomMappings; protected final List<Consumer<LiveMapper>> onCustomMappings;
protected final List<Consumer<DependanceContainerBuilder>> onCustomDependencies; protected final List<Consumer<DependanceContainerBuilder>> onCustomDependencies;
public TikTokLiveClientBuilder(String userName) { public TikTokLiveClientBuilder(String userName) {
@@ -75,7 +65,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
this.onCustomDependencies = new ArrayList<>(); this.onCustomDependencies = new ArrayList<>();
} }
public LiveClientBuilder onMapping(Consumer<TikTokMapper> consumer) { public LiveClientBuilder onMapping(Consumer<LiveMapper> consumer) {
this.onCustomMappings.add(consumer); this.onCustomMappings.add(consumer);
return this; return this;
} }
@@ -133,8 +123,8 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
}); });
//messages //messages
dependance.registerSingleton(TikTokLiveEventHandler.class, eventHandler); dependance.registerSingleton(LiveEventsHandler.class, eventHandler);
dependance.registerSingleton(TikTokLiveMessageHandler.class); dependance.registerSingleton(LiveMessagesHandler.class,TikTokLiveMessageHandler.class);
//listeners //listeners
dependance.registerSingletonList(TikTokEventListener.class, (e) -> listeners); dependance.registerSingletonList(TikTokEventListener.class, (e) -> listeners);
@@ -142,6 +132,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
//networking //networking
dependance.registerSingleton(HttpClientFactory.class); dependance.registerSingleton(HttpClientFactory.class);
dependance.registerSingleton(TikTokWebSocketPingingTask.class);
if (clientSettings.isOffline()) { if (clientSettings.isOffline()) {
dependance.registerSingleton(SocketClient.class, TikTokWebSocketOfflineClient.class); dependance.registerSingleton(SocketClient.class, TikTokWebSocketOfflineClient.class);
dependance.registerSingleton(LiveHttpClient.class, TikTokLiveHttpOfflineClient.class); dependance.registerSingleton(LiveHttpClient.class, TikTokLiveHttpOfflineClient.class);
@@ -166,8 +157,8 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
//mapper //mapper
dependance.registerSingleton(TikTokGenericEventMapper.class); dependance.registerSingleton(TikTokGenericEventMapper.class);
dependance.registerSingleton(TikTokMapperHelper.class, TikTokLiveMapperHelper.class); dependance.registerSingleton(LiveMapperHelper.class, TikTokLiveMapperHelper.class);
dependance.registerSingleton(TikTokMapper.class, (container) -> dependance.registerSingleton(LiveMapper.class, (container) ->
{ {
var dependace = (DependanceContainer) container.find(DependanceContainer.class); var dependace = (DependanceContainer) container.find(DependanceContainer.class);
var mapper = MessagesMapperFactory.create(dependace); var mapper = MessagesMapperFactory.create(dependace);

View File

@@ -23,12 +23,13 @@
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.live.LiveEventsHandler;
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer; import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import java.util.*; import java.util.*;
public class TikTokLiveEventHandler { public class TikTokLiveEventHandler implements LiveEventsHandler {
private final Map<Class<?>, Set<EventConsumer>> events; private final Map<Class<?>, Set<EventConsumer>> events;
public TikTokLiveEventHandler() { public TikTokLiveEventHandler() {

View File

@@ -30,21 +30,22 @@ import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketRespons
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandledMessageEvent; import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandledMessageEvent;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapper; import io.github.jwdeveloper.tiktok.live.LiveEventsHandler;
import io.github.jwdeveloper.tiktok.mappers.TikTokMapper; import io.github.jwdeveloper.tiktok.live.LiveMessagesHandler;
import io.github.jwdeveloper.tiktok.mappers.LiveMapper;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import io.github.jwdeveloper.tiktok.utils.Stopwatch; import io.github.jwdeveloper.tiktok.utils.Stopwatch;
import java.time.Duration; import java.time.Duration;
public class TikTokLiveMessageHandler { public class TikTokLiveMessageHandler implements LiveMessagesHandler {
private final TikTokLiveEventHandler tikTokEventHandler; private final LiveEventsHandler tikTokEventHandler;
private final TikTokLiveMapper mapper; private final LiveMapper mapper;
public TikTokLiveMessageHandler(TikTokLiveEventHandler tikTokEventHandler, TikTokMapper mapper) { public TikTokLiveMessageHandler(TikTokLiveEventHandler tikTokEventHandler, LiveMapper mapper) {
this.tikTokEventHandler = tikTokEventHandler; this.tikTokEventHandler = tikTokEventHandler;
this.mapper = (TikTokLiveMapper) mapper; this.mapper = mapper;
} }
public void handle(LiveClient client, WebcastResponse webcastResponse) { public void handle(LiveClient client, WebcastResponse webcastResponse) {
@@ -59,11 +60,9 @@ public class TikTokLiveMessageHandler {
} }
} }
public void handleSingleMessage(LiveClient client, WebcastResponse.Message message) public void handleSingleMessage(LiveClient client, WebcastResponse.Message message) {
{
var messageClassName = message.getMethod(); var messageClassName = message.getMethod();
if (!mapper.isRegistered(messageClassName)) if (!mapper.isRegistered(messageClassName)) {
{
tikTokEventHandler.publish(client, new TikTokWebsocketUnhandledMessageEvent(message)); tikTokEventHandler.publish(client, new TikTokWebsocketUnhandledMessageEvent(message));
return; return;
} }

View File

@@ -36,13 +36,4 @@ public class HttpClientFactory {
public HttpClientBuilder client(String url) { public HttpClientBuilder client(String url) {
return new HttpClientBuilder(url, liveClientSettings.getHttpSettings().clone()); return new HttpClientBuilder(url, liveClientSettings.getHttpSettings().clone());
} }
//Does not contains default httpClientSettings, Params, headers, etd
//Edit: Do we even use it?
public HttpClientBuilder clientEmpty(String url) {
var settings = new HttpClientSettings();
settings.setProxyClientSettings(liveClientSettings.getHttpSettings().getProxyClientSettings());
return new HttpClientBuilder(url, settings);
}
} }

View File

@@ -29,6 +29,7 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.exceptions.TikTokEventListenerMethodException; import io.github.jwdeveloper.tiktok.exceptions.TikTokEventListenerMethodException;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.live.LiveEventsHandler;
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer; import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
import java.util.ArrayList; import java.util.ArrayList;
@@ -37,10 +38,10 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
public class TikTokListenersManager implements ListenersManager { public class TikTokListenersManager implements ListenersManager {
private final TikTokLiveEventHandler eventObserver; private final LiveEventsHandler eventObserver;
private final List<ListenerBindingModel> bindingModels; private final List<ListenerBindingModel> bindingModels;
public TikTokListenersManager(List<TikTokEventListener> listeners, TikTokLiveEventHandler tikTokEventHandler) { public TikTokListenersManager(List<TikTokEventListener> listeners, LiveEventsHandler tikTokEventHandler) {
this.eventObserver = tikTokEventHandler; this.eventObserver = tikTokEventHandler;
this.bindingModels = new ArrayList<>(listeners.size()); this.bindingModels = new ArrayList<>(listeners.size());
for (var listener : listeners) { for (var listener : listeners) {

View File

@@ -23,11 +23,8 @@
package io.github.jwdeveloper.tiktok.mappers; package io.github.jwdeveloper.tiktok.mappers;
import io.github.jwdeveloper.dependance.api.DependanceContainer; import io.github.jwdeveloper.dependance.api.DependanceContainer;
import io.github.jwdeveloper.dependance.injector.api.containers.Container;
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
import io.github.jwdeveloper.tiktok.data.events.*; import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.tiktok.data.events.link.*; import io.github.jwdeveloper.tiktok.data.events.link.*;
import io.github.jwdeveloper.tiktok.live.GiftsManager;
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult; import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokCommonEventHandler; import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokCommonEventHandler;
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokGiftEventHandler; import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokGiftEventHandler;
@@ -40,7 +37,7 @@ import static io.github.jwdeveloper.tiktok.messages.enums.LinkMessageType.*;
public class MessagesMapperFactory { public class MessagesMapperFactory {
public static TikTokLiveMapper create(DependanceContainer container) { public static TikTokLiveMapper create(DependanceContainer container) {
var helper = container.find(TikTokMapperHelper.class); var helper = container.find(LiveMapperHelper.class);
var mapper = new TikTokLiveMapper(helper); var mapper = new TikTokLiveMapper(helper);
//ConnectionEvents events //ConnectionEvents events

View File

@@ -29,13 +29,13 @@ import io.github.jwdeveloper.tiktok.mappers.data.*;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
public class TikTokLiveMapper implements TikTokMapper { public class TikTokLiveMapper implements LiveMapper {
private final Map<String, TikTokLiveMapperModel> mappers; private final Map<String, TikTokLiveMapperModel> mappers;
private final TikTokMapperHelper mapperUtils; private final LiveMapperHelper mapperUtils;
private final TikTokLiveMapperModel globalMapperModel; private final TikTokLiveMapperModel globalMapperModel;
public TikTokLiveMapper(TikTokMapperHelper mapperUtils) { public TikTokLiveMapper(LiveMapperHelper mapperUtils) {
this.mappers = new HashMap<>(); this.mappers = new HashMap<>();
this.mapperUtils = mapperUtils; this.mapperUtils = mapperUtils;
this.globalMapperModel = new TikTokLiveMapperModel("any message"); this.globalMapperModel = new TikTokLiveMapperModel("any message");

View File

@@ -28,7 +28,7 @@ import io.github.jwdeveloper.tiktok.utils.JsonUtil;
import io.github.jwdeveloper.tiktok.utils.ProtoBufferObject; import io.github.jwdeveloper.tiktok.utils.ProtoBufferObject;
import io.github.jwdeveloper.tiktok.utils.ProtocolUtils; import io.github.jwdeveloper.tiktok.utils.ProtocolUtils;
public class TikTokLiveMapperHelper implements TikTokMapperHelper { public class TikTokLiveMapperHelper implements LiveMapperHelper {
private final TikTokGenericEventMapper genericMapper; private final TikTokGenericEventMapper genericMapper;
public TikTokLiveMapperHelper(TikTokGenericEventMapper genericMapper) { public TikTokLiveMapperHelper(TikTokGenericEventMapper genericMapper) {

View File

@@ -28,7 +28,7 @@ import io.github.jwdeveloper.tiktok.data.events.gift.*;
import io.github.jwdeveloper.tiktok.data.models.Picture; import io.github.jwdeveloper.tiktok.data.models.Picture;
import io.github.jwdeveloper.tiktok.data.models.gifts.*; import io.github.jwdeveloper.tiktok.data.models.gifts.*;
import io.github.jwdeveloper.tiktok.live.GiftsManager; import io.github.jwdeveloper.tiktok.live.GiftsManager;
import io.github.jwdeveloper.tiktok.mappers.TikTokMapperHelper; import io.github.jwdeveloper.tiktok.mappers.LiveMapperHelper;
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult; import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
import lombok.SneakyThrows; import lombok.SneakyThrows;
@@ -48,7 +48,7 @@ public class TikTokGiftEventHandler {
} }
@SneakyThrows @SneakyThrows
public MappingResult handleGifts(byte[] msg, String name, TikTokMapperHelper helper) { public MappingResult handleGifts(byte[] msg, String name, LiveMapperHelper helper) {
var currentMessage = WebcastGiftMessage.parseFrom(msg); var currentMessage = WebcastGiftMessage.parseFrom(msg);
var gifts = handleGift(currentMessage); var gifts = handleGift(currentMessage);
return MappingResult.of(currentMessage, gifts); return MappingResult.of(currentMessage, gifts);

View File

@@ -31,7 +31,7 @@ import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent; import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
import io.github.jwdeveloper.tiktok.data.models.RankingUser; import io.github.jwdeveloper.tiktok.data.models.RankingUser;
import io.github.jwdeveloper.tiktok.data.models.users.User; import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.mappers.TikTokMapperHelper; import io.github.jwdeveloper.tiktok.mappers.LiveMapperHelper;
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult; import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLikeMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLikeMessage;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLiveIntroMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLiveIntroMessage;
@@ -86,7 +86,7 @@ public class TikTokRoomInfoEventHandler {
} }
@SneakyThrows @SneakyThrows
public MappingResult handleMemberMessage(byte[] msg, String name, TikTokMapperHelper helper) { public MappingResult handleMemberMessage(byte[] msg, String name, LiveMapperHelper helper) {
var message = WebcastMemberMessage.parseFrom(msg); var message = WebcastMemberMessage.parseFrom(msg);
var event = switch (message.getAction()) { var event = switch (message.getAction()) {
@@ -103,7 +103,7 @@ public class TikTokRoomInfoEventHandler {
} }
@SneakyThrows @SneakyThrows
public MappingResult handleLike(byte[] msg, String name, TikTokMapperHelper helper) { public MappingResult handleLike(byte[] msg, String name, LiveMapperHelper helper) {
var message = WebcastLikeMessage.parseFrom(msg); var message = WebcastLikeMessage.parseFrom(msg);
var event = new TikTokLikeEvent(message); var event = new TikTokLikeEvent(message);
var roomInfoEvent = this.handleRoomInfo(tikTokRoomInfo -> var roomInfoEvent = this.handleRoomInfo(tikTokRoomInfo ->

View File

@@ -29,6 +29,8 @@ 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.*; import io.github.jwdeveloper.tiktok.exceptions.*;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.live.LiveEventsHandler;
import io.github.jwdeveloper.tiktok.live.LiveMessagesHandler;
import org.java_websocket.client.WebSocketClient; import org.java_websocket.client.WebSocketClient;
import javax.net.ssl.*; import javax.net.ssl.*;
@@ -38,22 +40,23 @@ import java.util.HashMap;
public class TikTokWebSocketClient implements SocketClient { public class TikTokWebSocketClient implements SocketClient {
private final LiveClientSettings clientSettings; private final LiveClientSettings clientSettings;
private final TikTokLiveMessageHandler messageHandler; private final LiveMessagesHandler messageHandler;
private final TikTokLiveEventHandler tikTokEventHandler; private final LiveEventsHandler tikTokEventHandler;
private WebSocketClient webSocketClient;
private final TikTokWebSocketPingingTask pingingTask; private final TikTokWebSocketPingingTask pingingTask;
private WebSocketClient webSocketClient;
private boolean isConnected; private boolean isConnected;
public TikTokWebSocketClient( public TikTokWebSocketClient(
LiveClientSettings clientSettings, LiveClientSettings clientSettings,
TikTokLiveMessageHandler messageHandler, LiveMessagesHandler messageHandler,
TikTokLiveEventHandler tikTokEventHandler) { LiveEventsHandler tikTokEventHandler,
TikTokWebSocketPingingTask pingingTask)
{
this.clientSettings = clientSettings; this.clientSettings = clientSettings;
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
this.tikTokEventHandler = tikTokEventHandler; this.tikTokEventHandler = tikTokEventHandler;
this.pingingTask = pingingTask;
isConnected = false; isConnected = false;
pingingTask = new TikTokWebSocketPingingTask();
} }
@Override @Override
@@ -64,7 +67,7 @@ public class TikTokWebSocketClient implements SocketClient {
messageHandler.handle(liveClient, connectionData.getWebcastResponse()); messageHandler.handle(liveClient, connectionData.getWebcastResponse());
var headers = new HashMap<>(clientSettings.getHttpSettings().getHeaders()); var headers = new HashMap<>(clientSettings.getHttpSettings().getHeaders());
headers.put("Cookie", connectionData.getWebsocketCookies()); headers.put("Cookie", connectionData.getWebsocketCookies());
webSocketClient = new TikTokWebSocketListener(connectionData.getWebsocketUrl(), webSocketClient = new TikTokWebSocketListener(connectionData.getWebsocketUrl(),
headers, headers,
@@ -96,9 +99,15 @@ public class TikTokWebSocketClient implements SocketClient {
if (proxySettings.getType() == Proxy.Type.SOCKS) { if (proxySettings.getType() == Proxy.Type.SOCKS) {
SSLContext sc = SSLContext.getInstance("SSL"); SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new X509TrustManager() { sc.init(null, new TrustManager[]{new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {} public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {} }
public X509Certificate[] getAcceptedIssuers() { return null; }
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}}, null); }}, null);
webSocketClient.setSocketFactory(sc.getSocketFactory()); webSocketClient.setSocketFactory(sc.getSocketFactory());
} }

View File

@@ -27,6 +27,8 @@ import io.github.jwdeveloper.tiktok.*;
import io.github.jwdeveloper.tiktok.data.events.*; import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.tiktok.exceptions.TikTokProtocolBufferException; import io.github.jwdeveloper.tiktok.exceptions.TikTokProtocolBufferException;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.live.LiveEventsHandler;
import io.github.jwdeveloper.tiktok.live.LiveMessagesHandler;
import io.github.jwdeveloper.tiktok.messages.webcast.*; import io.github.jwdeveloper.tiktok.messages.webcast.*;
import org.java_websocket.client.WebSocketClient; import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455; import org.java_websocket.drafts.Draft_6455;
@@ -38,15 +40,15 @@ import java.util.*;
public class TikTokWebSocketListener extends WebSocketClient { public class TikTokWebSocketListener extends WebSocketClient {
private final TikTokLiveMessageHandler messageHandler; private final LiveMessagesHandler messageHandler;
private final TikTokLiveEventHandler tikTokEventHandler; private final LiveEventsHandler tikTokEventHandler;
private final LiveClient tikTokLiveClient; private final LiveClient tikTokLiveClient;
public TikTokWebSocketListener(URI serverUri, public TikTokWebSocketListener(URI serverUri,
Map<String, String> httpHeaders, Map<String, String> httpHeaders,
int connectTimeout, int connectTimeout,
TikTokLiveMessageHandler messageHandler, LiveMessagesHandler messageHandler,
TikTokLiveEventHandler tikTokEventHandler, LiveEventsHandler tikTokEventHandler,
LiveClient tikTokLiveClient) { LiveClient tikTokLiveClient) {
super(serverUri, new Draft_6455(), httpHeaders, connectTimeout); super(serverUri, new Draft_6455(), httpHeaders, connectTimeout);
this.messageHandler = messageHandler; this.messageHandler = messageHandler;

View File

@@ -27,13 +27,14 @@ import io.github.jwdeveloper.tiktok.data.events.TikTokConnectedEvent;
import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent; import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData; import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.live.LiveEventsHandler;
public class TikTokWebSocketOfflineClient implements SocketClient { public class TikTokWebSocketOfflineClient implements SocketClient {
private final TikTokLiveEventHandler handler; private final LiveEventsHandler handler;
private LiveClient liveClient; private LiveClient liveClient;
public TikTokWebSocketOfflineClient(TikTokLiveEventHandler handler) { public TikTokWebSocketOfflineClient(LiveEventsHandler handler) {
this.handler = handler; this.handler = handler;
} }

View File

@@ -22,41 +22,37 @@
*/ */
package io.github.jwdeveloper.tiktok.websocket; package io.github.jwdeveloper.tiktok.websocket;
import io.github.jwdeveloper.tiktok.live.LiveEventsHandler;
import org.java_websocket.WebSocket; import org.java_websocket.WebSocket;
public class TikTokWebSocketPingingTask public class TikTokWebSocketPingingTask {
{
private Thread thread; private Thread thread;
private boolean isRunning = false; private boolean isRunning = false;
private final int MAX_TIMEOUT = 250; private final int MAX_TIMEOUT = 250;
private final int SLEEP_TIME = 500; private final int SLEEP_TIME = 500;
public void run(WebSocket webSocket, long pingTaskTime) public void run(WebSocket webSocket, long pingTaskTime) {
{
stop(); stop();
thread = new Thread(() -> pingTask(webSocket, pingTaskTime), "pinging-task"); thread = new Thread(() -> pingTask(webSocket, pingTaskTime), "pinging-task");
isRunning = true; isRunning = true;
thread.start(); thread.start();
} }
public void stop() public void stop() {
{
if (thread != null) if (thread != null)
thread.interrupt(); thread.interrupt();
isRunning = false; isRunning = false;
} }
private void pingTask(WebSocket webSocket, long pingTaskTime) private void pingTask(WebSocket webSocket, long pingTaskTime) {
{
while (isRunning) { while (isRunning) {
try { try {
if (webSocket.isOpen()) { if (webSocket.isOpen()) {
webSocket.sendPing(); webSocket.sendPing();
Thread.sleep(pingTaskTime+(int)(Math.random() * MAX_TIMEOUT)); Thread.sleep(pingTaskTime + (int) (Math.random() * MAX_TIMEOUT));
} else } else
Thread.sleep(SLEEP_TIME); Thread.sleep(SLEEP_TIME);
} } catch (Exception e) {
catch (Exception e) {
//TODO we should display some kind of error message //TODO we should display some kind of error message
isRunning = false; isRunning = false;
} }

View File

@@ -1,55 +0,0 @@
/*
* 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.common;
import java.io.IOException;
import java.util.Base64;
public class TikTokBaseTest
{
public byte[] getFileBytes(String path)
{
try {
var stream = getClass().getClassLoader().getResourceAsStream(path);
var bytes= stream.readAllBytes();
stream.close();
return bytes;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public byte[] getFileBytesUtf(String path)
{
try {
var stream = getClass().getClassLoader().getResourceAsStream(path);
var bytes= stream.readAllBytes();
stream.close();
return Base64.getDecoder().decode(bytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -1,38 +0,0 @@
/*
* 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.gifts;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class TikTokGiftManagerTest {
}