diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/annotations/Priority.java b/API/src/main/java/io/github/jwdeveloper/tiktok/annotations/Priority.java new file mode 100644 index 0000000..5ab1902 --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/annotations/Priority.java @@ -0,0 +1,18 @@ +package io.github.jwdeveloper.tiktok.annotations; + +/** + * HIGHEST 1 + * HIGH 2 + * NORMAL 3 + * LOW 4 + * LOWEST 5 + */ +public enum Priority { + LOWEST(2), LOW(1), NORMAL(0), HIGH(-1), HIGHEST(-2); + + public final int value; + + Priority(int value) { + this.value = value; + } +} \ No newline at end of file diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/annotations/TikTokEventObserver.java b/API/src/main/java/io/github/jwdeveloper/tiktok/annotations/TikTokEventObserver.java index 109af2d..08f5cb8 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/annotations/TikTokEventObserver.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/annotations/TikTokEventObserver.java @@ -28,5 +28,14 @@ import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface TikTokEventObserver { + /** + * When more than one method listen for certain Event, you can specify the method priority + * @see Priority + */ + Priority priority() default Priority.NORMAL; + /** + * When true, action is invoked on a thread, from the threads pool + */ + boolean async() default false; } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLinkMicBattleEvent.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLinkMicBattleEvent.java index adcea27..13b4271 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLinkMicBattleEvent.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLinkMicBattleEvent.java @@ -43,8 +43,6 @@ public class TikTokLinkMicBattleEvent extends TikTokHeaderEvent true if battle is finished otherwise false */ private final boolean finished; - @Getter(AccessLevel.NONE) - private final boolean oneVsOne; private final List teams; public TikTokLinkMicBattleEvent(WebcastLinkMicBattle msg) { @@ -55,7 +53,6 @@ public class TikTokLinkMicBattleEvent extends TikTokHeaderEvent if (msg.getHostTeamCount() == 2) { // 1v1 battle teams.add(new Team1v1(msg.getHostTeam(0), msg)); teams.add(new Team1v1(msg.getHostTeam(1), msg)); - oneVsOne = true; } else { // 2v2 battle if (isFinished()) { teams.add(new Team2v2(msg.getHostData2V2List().stream().filter(data -> data.getTeamNumber() == 1).findFirst().orElse(null), msg)); @@ -64,7 +61,6 @@ public class TikTokLinkMicBattleEvent extends TikTokHeaderEvent teams.add(new Team2v2(msg.getHostTeam(0), msg.getHostTeam(1), msg)); teams.add(new Team2v2(msg.getHostTeam(2), msg.getHostTeam(3), msg)); } - oneVsOne = false; } // Info: @@ -74,10 +70,14 @@ public class TikTokLinkMicBattleEvent extends TikTokHeaderEvent } public boolean is1v1() { - return oneVsOne; + return teams.get(0) instanceof Team1v1; } public boolean is2v2() { - return !oneVsOne; + return teams.get(0) instanceof Team2v2; + } + + public boolean isTie() { + return isFinished() && teams.get(0).getTotalPoints() == teams.get(1).getTotalPoints(); } } \ No newline at end of file diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team.java index dc8554f..18a85d6 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team.java @@ -22,7 +22,12 @@ */ package io.github.jwdeveloper.tiktok.data.models.battles; +import lombok.Getter; + public abstract class Team { + /** Value >= 0 when finished otherwise -1 */ + @Getter protected int totalPoints; + /** * Provides a check for verifying if this team represents a 1v1 Team. * @return true if this team is of type {@link Team1v1}, false otherwise. diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team1v1.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team1v1.java index 9462e67..973da62 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team1v1.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team1v1.java @@ -29,10 +29,7 @@ import lombok.Getter; import java.util.*; @Getter -public class Team1v1 extends Team -{ - /** Value >= 0 when finished otherwise -1 */ - private final int totalPoints; +public class Team1v1 extends Team { private final int winStreak; private final User host; private final List viewers; diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team2v2.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team2v2.java index b843f45..f484dbc 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team2v2.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/battles/Team2v2.java @@ -30,9 +30,6 @@ import java.util.*; @Getter public class Team2v2 extends Team { - /** Value >= 0 when finished otherwise -1 */ - private final int totalPoints; - private final List hosts; private final List viewers; diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/listener/ListenersManager.java b/API/src/main/java/io/github/jwdeveloper/tiktok/listener/ListenersManager.java index 09f430a..05df523 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/listener/ListenersManager.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/listener/ListenersManager.java @@ -25,16 +25,13 @@ package io.github.jwdeveloper.tiktok.listener; import java.util.List; /** - * You can dynamically add or removing TikTokEventListener - * - * @see TikTokEventListener - * + * Manage events listeners objects */ public interface ListenersManager { - List getListeners(); + List getListeners(); - void addListener(TikTokEventListener listener); + void addListener(Object listener); - void removeListener(TikTokEventListener listener); + void removeListener(Object listener); } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/listener/TikTokEventListener.java b/API/src/main/java/io/github/jwdeveloper/tiktok/listener/TikTokEventListener.java index f230100..cf70bca 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/listener/TikTokEventListener.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/listener/TikTokEventListener.java @@ -40,7 +40,7 @@ import io.github.jwdeveloper.tiktok.live.LiveClient; * {@code * public static class CustomListener implements TikTokEventListener * { - * @TikTokEventObserver + * @TikTokEventObserver * public void onError(LiveClient liveClient, TikTokErrorEvent event) * { * System.out.println(event.getException().getMessage()); @@ -67,7 +67,9 @@ import io.github.jwdeveloper.tiktok.live.LiveClient; * } * */ -public interface TikTokEventListener -{ +//TODO I think this interface can be removed, since we are using, +//annotation @TikTokEventHandler to check methods that are events +@Deprecated(forRemoval = true, since = "1.8.1 (This interface is not longer needed, please remove it from your class)") +public interface TikTokEventListener { } \ No newline at end of file diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/LiveClientBuilder.java b/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/LiveClientBuilder.java index 26c6004..8e343c9 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/LiveClientBuilder.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/LiveClientBuilder.java @@ -24,7 +24,6 @@ package io.github.jwdeveloper.tiktok.live.builder; import io.github.jwdeveloper.dependance.implementation.DependanceContainerBuilder; import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; -import io.github.jwdeveloper.tiktok.listener.TikTokEventListener; import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.mappers.LiveMapper; @@ -33,40 +32,43 @@ import java.util.function.Consumer; public interface LiveClientBuilder extends EventsBuilder { + /** * This method is triggered after default mappings are registered * It could be used to OVERRIDE behaviour of mappings and implement custom behaviour - * + *

* Be aware if for example you override WebcastGiftEvent, onGiftEvent() will not be working * * @param onCustomMappings lambda method * @return */ - LiveClientBuilder onMapping(Consumer onCustomMappings); + LiveClientBuilder mappings(Consumer onCustomMappings); + @Deprecated(forRemoval = true, since = "1.8.2 use `mappings` method instead") + LiveClientBuilder onMappings(Consumer onCustomMappings); /** * Configuration of client settings - * @see LiveClientSettings + * * @param onConfigure * @return + * @see LiveClientSettings */ LiveClientBuilder configure(Consumer onConfigure); /** - * @see TikTokEventListener * Adding events listener class, its fancy way to register events without using lamda method * but actual method in class that implements TikTokEventListener + * * @return */ - LiveClientBuilder addListener(TikTokEventListener listener); + LiveClientBuilder addListener(Object listener); /** * Allows you to use own implementation of internal TikTokLive dependencies, * when the default implementation does not meet your needs * - * * @param onCustomizeDependencies access to dependency container * @return */ @@ -74,18 +76,19 @@ public interface LiveClientBuilder extends EventsBuilder { /** * Builds new instance of the LiveClient + * * @return LiveClient object */ LiveClient build(); /** * Builds new instance of the LiveClient and connects to live + * * @return LiveClient object */ LiveClient buildAndConnect(); /** - * * @return LiveClient object and connects to TikTok live asynchronously */ CompletableFuture buildAndConnectAsync(); diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/websocket/SocketClient.java b/API/src/main/java/io/github/jwdeveloper/tiktok/websocket/LiveSocketClient.java similarity index 93% rename from API/src/main/java/io/github/jwdeveloper/tiktok/websocket/SocketClient.java rename to API/src/main/java/io/github/jwdeveloper/tiktok/websocket/LiveSocketClient.java index 241c34c..dca7979 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/websocket/SocketClient.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/websocket/LiveSocketClient.java @@ -24,9 +24,8 @@ package io.github.jwdeveloper.tiktok.websocket; import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData; import io.github.jwdeveloper.tiktok.live.LiveClient; -import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; -public interface SocketClient { +public interface LiveSocketClient { void start(LiveConnectionData.Response webcastResponse, LiveClient tikTokLiveClient); void stop(); } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClient.java index 834e227..653f184 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClient.java @@ -36,7 +36,7 @@ import io.github.jwdeveloper.tiktok.listener.*; import io.github.jwdeveloper.tiktok.live.*; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; import io.github.jwdeveloper.tiktok.models.ConnectionState; -import io.github.jwdeveloper.tiktok.websocket.SocketClient; +import io.github.jwdeveloper.tiktok.websocket.LiveSocketClient; import lombok.Getter; import java.util.Base64; @@ -49,7 +49,7 @@ public class TikTokLiveClient implements LiveClient { private final TikTokRoomInfo roomInfo; private final LiveHttpClient httpClient; - private final SocketClient webSocketClient; + private final LiveSocketClient webSocketClient; private final LiveEventsHandler tikTokEventHandler; private final LiveClientSettings clientSettings; private final ListenersManager listenersManager; @@ -62,7 +62,7 @@ public class TikTokLiveClient implements LiveClient GiftsManager giftsManager, TikTokRoomInfo tikTokLiveMeta, LiveHttpClient tiktokHttpClient, - SocketClient webSocketClient, + LiveSocketClient webSocketClient, LiveEventsHandler tikTokEventHandler, LiveClientSettings clientSettings, ListenersManager listenersManager, @@ -78,17 +78,6 @@ public class TikTokLiveClient implements LiveClient this.logger = logger; } - public void connectAsync(Consumer onConnection) { - connectAsync().thenAccept(onConnection); - } - - public CompletableFuture connectAsync() { - return CompletableFuture.supplyAsync(() -> { - connect(); - return this; - }); - } - public void connect() { try { tryConnect(); @@ -199,4 +188,15 @@ public class TikTokLiveClient implements LiveClient messageHandler.handleSingleMessage(this, message); } + + public void connectAsync(Consumer onConnection) { + connectAsync().thenAccept(onConnection); + } + + public CompletableFuture connectAsync() { + return CompletableFuture.supplyAsync(() -> { + connect(); + return this; + }); + } } \ No newline at end of file diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java index 581b28b..8c01568 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java @@ -52,7 +52,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder { protected final LiveClientSettings clientSettings; protected final LiveEventsHandler eventHandler; - protected final List listeners; + protected final List listeners; protected final List> onCustomMappings; protected final List> onCustomDependencies; @@ -65,17 +65,23 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder { this.onCustomDependencies = new ArrayList<>(); } - public LiveClientBuilder onMapping(Consumer consumer) { + public LiveClientBuilder mappings(Consumer consumer) { this.onCustomMappings.add(consumer); return this; } + @Override + public LiveClientBuilder onMappings(Consumer onCustomMappings) { + mappings(onCustomMappings); + return this; + } + public TikTokLiveClientBuilder configure(Consumer onConfigure) { onConfigure.accept(clientSettings); return this; } - public TikTokLiveClientBuilder addListener(TikTokEventListener listener) { + public TikTokLiveClientBuilder addListener(Object listener) { if (listener != null) listeners.add(listener); return this; @@ -97,8 +103,9 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder { if (clientSettings.getHostName().startsWith("@")) clientSettings.setHostName(clientSettings.getHostName().substring(1)); + //TODO 250 Magic number if (clientSettings.getPingInterval() < 250) - throw new TikTokLiveException("Minimum allowed ping interval is 250 millseconds"); + throw new TikTokLiveException("Minimum allowed ping interval is 250 milliseconds"); var httpSettings = clientSettings.getHttpSettings(); httpSettings.getParams().put("app_language", clientSettings.getClientLanguage()); @@ -124,20 +131,19 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder { //messages dependance.registerSingleton(LiveEventsHandler.class, eventHandler); - dependance.registerSingleton(LiveMessagesHandler.class,TikTokLiveMessageHandler.class); + dependance.registerSingleton(LiveMessagesHandler.class, TikTokLiveMessageHandler.class); //listeners - dependance.registerSingletonList(TikTokEventListener.class, (e) -> listeners); dependance.registerSingleton(ListenersManager.class, TikTokListenersManager.class); //networking dependance.registerSingleton(HttpClientFactory.class); dependance.registerSingleton(TikTokWebSocketPingingTask.class); if (clientSettings.isOffline()) { - dependance.registerSingleton(SocketClient.class, TikTokWebSocketOfflineClient.class); + dependance.registerSingleton(LiveSocketClient.class, TikTokWebSocketOfflineClient.class); dependance.registerSingleton(LiveHttpClient.class, TikTokLiveHttpOfflineClient.class); } else { - dependance.registerSingleton(SocketClient.class, TikTokWebSocketClient.class); + dependance.registerSingleton(LiveSocketClient.class, TikTokWebSocketClient.class); dependance.registerSingleton(LiveHttpClient.class, TikTokLiveHttpClient.class); } @@ -176,8 +182,10 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder { dependance.registerSingleton(LiveClient.class, TikTokLiveClient.class); onCustomDependencies.forEach(action -> action.accept(dependance)); - var container = dependance.build(); + + var listenerManager = container.find(ListenersManager.class); + listeners.forEach(listenerManager::addListener); return container.find(LiveClient.class); } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java index 2637e3f..b1ccee8 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java @@ -136,7 +136,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient var url = TIKTOK_URL_WEB + "api-live/user/room"; var result = httpFactory.client(url) .withParam("uniqueId", request.getUserName()) - .withParam("sourceType", "54") + .withParam("sourceType", "54") //MAGIC NUMBER, WHAT 54 means? .build() .toJsonResponse(); @@ -218,7 +218,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient private ActionResult> getByteResponse(String room_id) { HttpClientBuilder builder = httpFactory.client(TIKTOK_SIGN_API) .withParam("client", "ttlive-java") - .withParam("uuc", "1") + .withParam("uuc", "1") //MAGIC NUMBER! .withParam("room_id", room_id); if (clientSettings.getApiKey() != null) diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/listener/ListenerBindingModel.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/listener/ListenerMethodInfo.java similarity index 78% rename from Client/src/main/java/io/github/jwdeveloper/tiktok/listener/ListenerBindingModel.java rename to Client/src/main/java/io/github/jwdeveloper/tiktok/listener/ListenerMethodInfo.java index a6fee10..7b9f085 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/listener/ListenerBindingModel.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/listener/ListenerMethodInfo.java @@ -22,19 +22,26 @@ */ package io.github.jwdeveloper.tiktok.listener; +import io.github.jwdeveloper.tiktok.annotations.Priority; + import io.github.jwdeveloper.tiktok.live.builder.EventConsumer; +import lombok.Data; -import lombok.Value; - -import java.util.List; -import java.util.Map; +import java.lang.reflect.Method; -@Value -public class ListenerBindingModel -{ +@Data +public class ListenerMethodInfo { + private Object listener; - TikTokEventListener listener; + private Class eventType; - Map, List>> events; + private Method method; + + private Priority priority; + + private boolean async; + + private EventConsumer action = (a, b) -> { + }; } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/listener/TikTokListenersManager.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/listener/TikTokListenersManager.java index ca981b7..1f482d9 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/listener/TikTokListenersManager.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/listener/TikTokListenersManager.java @@ -23,104 +23,135 @@ package io.github.jwdeveloper.tiktok.listener; -import io.github.jwdeveloper.tiktok.TikTokLiveEventHandler; +import io.github.jwdeveloper.dependance.api.DependanceContainer; 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.exceptions.TikTokEventListenerMethodException; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; -import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveEventsHandler; import io.github.jwdeveloper.tiktok.live.builder.EventConsumer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; +import java.lang.reflect.Method; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; public class TikTokListenersManager implements ListenersManager { - private final LiveEventsHandler eventObserver; - private final List bindingModels; - public TikTokListenersManager(List listeners, LiveEventsHandler tikTokEventHandler) { - this.eventObserver = tikTokEventHandler; - this.bindingModels = new ArrayList<>(listeners.size()); - for (var listener : listeners) { - addListener(listener); - } + private final Map> listeners; + private final LiveEventsHandler eventsHandler; + private final ExecutorService executorService; + private final DependanceContainer dependanceContainer; + + + public TikTokListenersManager(LiveEventsHandler tikTokEventHandler, + DependanceContainer dependanceContainer) { + this.eventsHandler = tikTokEventHandler; + this.dependanceContainer = dependanceContainer; + this.listeners = new HashMap<>(); + executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); } @Override - public List getListeners() { - return bindingModels.stream().map(ListenerBindingModel::getListener).toList(); + public List getListeners() { + return listeners.keySet().stream().toList(); } @Override - public void addListener(TikTokEventListener listener) { - var alreadyExists = bindingModels.stream().filter(e -> e.getListener() == listener).findAny(); - if (alreadyExists.isPresent()) { + public void addListener(Object listener) { + if (listeners.containsKey(listener)) { throw new TikTokLiveException("Listener " + listener.getClass() + " has already been registered"); } - var bindingModel = bindToEvents(listener); - for (var eventEntrySet : bindingModel.getEvents().entrySet()) { - var eventType = eventEntrySet.getKey(); - for (var methods : eventEntrySet.getValue()) { - eventObserver.subscribe(eventType, methods); - } + var methodsInfo = getMethodsInfo(listener); + for (var methodInfo : methodsInfo) { + eventsHandler.subscribe(methodInfo.getEventType(), methodInfo.getAction()); } - bindingModels.add(bindingModel); + listeners.put(listener, methodsInfo); } @Override - public void removeListener(TikTokEventListener listener) { - var optional = bindingModels.stream().filter(e -> e.getListener() == listener).findAny(); - if (optional.isEmpty()) { + public void removeListener(Object listener) { + if (!listeners.containsKey(listener)) { return; } - - var bindingModel = optional.get(); - - for (var eventEntrySet : bindingModel.getEvents().entrySet()) { - var eventType = eventEntrySet.getKey(); - for (var methods : eventEntrySet.getValue()) { - eventObserver.unsubscribe(eventType, methods); - } + var methodsInfo = listeners.get(listener); + for (var methodInfo : methodsInfo) { + eventsHandler.unsubscribe(methodInfo.getEventType(), methodInfo.getAction()); } - bindingModels.remove(optional.get()); + listeners.remove(listener); } - private ListenerBindingModel bindToEvents(TikTokEventListener listener) { + private List getMethodsInfo(Object listener) { + return Arrays.stream(listener.getClass().getDeclaredMethods()) + .filter(e -> e.isAnnotationPresent(TikTokEventObserver.class)) + .filter(e -> e.getParameterCount() >= 1) + .map(method -> getSingleMethodInfo(listener, method)) + .sorted(Comparator.comparingInt(a -> a.getPriority().value)) + .toList(); + } - var clazz = listener.getClass(); - var methods = Arrays.stream(clazz.getDeclaredMethods()).filter(m -> - m.getParameterCount() == 2 && - m.isAnnotationPresent(TikTokEventObserver.class)).toList(); - var eventsMap = new HashMap, List>>(); - for (var method : methods) { - var liveclientClass = method.getParameterTypes()[0]; - var eventClass = method.getParameterTypes()[1]; + private ListenerMethodInfo getSingleMethodInfo(Object listener, Method method) { - if (!LiveClient.class.isAssignableFrom(liveclientClass) && !liveclientClass.equals(LiveClient.class)) { - throw new TikTokEventListenerMethodException("Method " + method.getName() + "() 1st parameter must be instance of " + LiveClient.class.getName() - + " | Invalid parameter class: "+liveclientClass.getName()); - } + method.setAccessible(true); + var annotation = method.getAnnotation(TikTokEventObserver.class); + var tiktokEventType = Arrays.stream(method.getParameterTypes()) + .filter(TikTokEvent.class::isAssignableFrom) + .findFirst() + .orElseThrow(() -> new TikTokEventListenerMethodException("Method " + method.getName() + "() must have only one parameter that inherits from class " + TikTokEvent.class.getName())); - if (!TikTokEvent.class.isAssignableFrom(eventClass) && !eventClass.equals(TikTokEvent.class)) { - throw new TikTokEventListenerMethodException("Method " + method.getName() + "() 2nd parameter must be instance of " + TikTokEvent.class.getName() - + " | Invalid parameter class: "+eventClass.getName()); - } + var info = new ListenerMethodInfo(); + info.setListener(listener); + info.setAsync(annotation.async()); + info.setPriority(annotation.priority()); + info.setEventType(tiktokEventType); + info.setAction(createAction(listener, method, tiktokEventType)); - EventConsumer eventMethodRef = (liveClient, event) -> + if (info.isAsync()) { + var action = info.getAction(); + info.setAction((liveClient, event) -> { - try { - method.setAccessible(true); - method.invoke(listener, liveClient, event); - } catch (Exception e) { - throw new TikTokEventListenerMethodException(e); - } - }; - eventsMap.computeIfAbsent(eventClass, (a) -> new ArrayList<>()).add(eventMethodRef); + executorService.submit(() -> + { + action.onEvent(liveClient, event); + }); + }); } - return new ListenerBindingModel(listener, eventsMap); + return info; + } + + + //I know, implementation of this might look complicated + private EventConsumer createAction(Object listener, Method method, Class tiktokEventType) { + AtomicReference eventObjectRef = new AtomicReference<>(); + var methodContainer = dependanceContainer.createChildContainer() + .configure(configuration -> + { + //Modifying container, so it returns TikTokEvent object instance, + //when TikTokEvent type is encountered in the methods parameters + configuration.onInjection(injectionEvent -> + { + if (injectionEvent.input().isAssignableFrom(tiktokEventType)) { + return eventObjectRef.get(); + } + return injectionEvent.output(); + }); + }) + .build(); + + return (liveClient, event) -> + { + try { + eventObjectRef.set(event); + //Creating list of input objects based on method parameters + //Objects are received from container + var parameters = methodContainer.resolveParameters(method); + method.invoke(listener, parameters); + } catch (Exception e) { + eventsHandler.publish(liveClient, new TikTokErrorEvent(new TikTokEventListenerMethodException(e))); + } + }; } } \ No newline at end of file diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokGenericEventMapper.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokGenericEventMapper.java index a7e8a0c..0ec2843 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokGenericEventMapper.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokGenericEventMapper.java @@ -53,7 +53,7 @@ public class TikTokGenericEventMapper { private final Map, Method> methodCache; private final Map> constructorCache; - + private static final String PARSE_FIELD = "parseFrom"; public TikTokGenericEventMapper() { this.methodCache = new HashMap<>(); this.constructorCache = new HashMap<>(); @@ -75,7 +75,7 @@ public class TikTokGenericEventMapper { public Method getParsingMethod(Class input) throws RuntimeException { return methodCache.computeIfAbsent(input, aClass -> { try { - return aClass.getDeclaredMethod("parseFrom", byte[].class); + return aClass.getDeclaredMethod(PARSE_FIELD, byte[].class); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokLiveMapper.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokLiveMapper.java index e12f748..db9ea4b 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokLiveMapper.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokLiveMapper.java @@ -34,11 +34,12 @@ public class TikTokLiveMapper implements LiveMapper { private final Map mappers; private final LiveMapperHelper mapperUtils; private final TikTokLiveMapperModel globalMapperModel; + private static final String GLOBAL_MESSAGE = "GLOBAL MESSAGE"; public TikTokLiveMapper(LiveMapperHelper mapperUtils) { this.mappers = new HashMap<>(); this.mapperUtils = mapperUtils; - this.globalMapperModel = new TikTokLiveMapperModel("any message"); + this.globalMapperModel = new TikTokLiveMapperModel(GLOBAL_MESSAGE); } @Override diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokLiveMapperHelper.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokLiveMapperHelper.java index b7ea1eb..4f5cc5a 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokLiveMapperHelper.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokLiveMapperHelper.java @@ -29,6 +29,9 @@ import io.github.jwdeveloper.tiktok.utils.ProtoBufferObject; import io.github.jwdeveloper.tiktok.utils.ProtocolUtils; public class TikTokLiveMapperHelper implements LiveMapperHelper { + + private static final String PACKAGE_PREFIX = "io.github.jwdeveloper.tiktok.messages.webcast."; + private final TikTokGenericEventMapper genericMapper; public TikTokLiveMapperHelper(TikTokGenericEventMapper genericMapper) { @@ -39,6 +42,7 @@ public class TikTokLiveMapperHelper implements LiveMapperHelper { public T bytesToWebcastObject(byte[] bytes, Class messageClass) { try { var parsingMethod = genericMapper.getParsingMethod(messageClass); + //NULL is passed, since Parsing method is Static var sourceObject = parsingMethod.invoke(null, bytes); return (T) sourceObject; } catch (Exception e) { @@ -49,7 +53,7 @@ public class TikTokLiveMapperHelper implements LiveMapperHelper { @Override public Object bytesToWebcastObject(byte[] bytes, String messageName) { try { - var packageName = "io.github.jwdeveloper.tiktok.messages.webcast." + messageName; + var packageName = PACKAGE_PREFIX + messageName; var clazz = Class.forName(packageName); return bytesToWebcastObject(bytes, (Class) clazz); } catch (Exception e) { @@ -60,7 +64,7 @@ public class TikTokLiveMapperHelper implements LiveMapperHelper { @Override public boolean isMessageHasProtoClass(String messageName) { try { - var packageName = "io.github.jwdeveloper.tiktok.messages.webcast." + messageName; + var packageName = PACKAGE_PREFIX + messageName; Class.forName(packageName); return true; } catch (Exception e) { diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/handlers/TikTokGiftEventHandler.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/handlers/TikTokGiftEventHandler.java index cd4293d..91526b3 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/handlers/TikTokGiftEventHandler.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/handlers/TikTokGiftEventHandler.java @@ -38,7 +38,6 @@ import java.util.*; public class TikTokGiftEventHandler { private final Map giftsMessages; private final TikTokRoomInfo tikTokRoomInfo; - private final GiftsManager giftsManager; public TikTokGiftEventHandler(GiftsManager giftsManager, TikTokRoomInfo tikTokRoomInfo) { diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java index 0b251b3..a4d36c5 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java @@ -22,8 +22,6 @@ */ package io.github.jwdeveloper.tiktok.websocket; -import io.github.jwdeveloper.dependance.injector.api.containers.Container; -import io.github.jwdeveloper.tiktok.*; import io.github.jwdeveloper.tiktok.data.dto.ProxyData; import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData; import io.github.jwdeveloper.tiktok.data.settings.*; @@ -38,7 +36,7 @@ import java.net.Proxy; import java.security.cert.X509Certificate; import java.util.HashMap; -public class TikTokWebSocketClient implements SocketClient { +public class TikTokWebSocketClient implements LiveSocketClient { private final LiveClientSettings clientSettings; private final LiveMessagesHandler messageHandler; private final LiveEventsHandler tikTokEventHandler; diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketListener.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketListener.java index 2699cd5..1d10d90 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketListener.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketListener.java @@ -23,7 +23,6 @@ package io.github.jwdeveloper.tiktok.websocket; import com.google.protobuf.ByteString; -import io.github.jwdeveloper.tiktok.*; import io.github.jwdeveloper.tiktok.data.events.*; import io.github.jwdeveloper.tiktok.exceptions.TikTokProtocolBufferException; import io.github.jwdeveloper.tiktok.live.LiveClient; @@ -40,9 +39,9 @@ import java.util.*; public class TikTokWebSocketListener extends WebSocketClient { - private final LiveMessagesHandler messageHandler; - private final LiveEventsHandler tikTokEventHandler; - private final LiveClient tikTokLiveClient; + private final LiveMessagesHandler messagesHandler; + private final LiveEventsHandler eventHandler; + private final LiveClient liveClient; public TikTokWebSocketListener(URI serverUri, Map httpHeaders, @@ -51,9 +50,9 @@ public class TikTokWebSocketListener extends WebSocketClient { LiveEventsHandler tikTokEventHandler, LiveClient tikTokLiveClient) { super(serverUri, new Draft_6455(), httpHeaders, connectTimeout); - this.messageHandler = messageHandler; - this.tikTokEventHandler = tikTokEventHandler; - this.tikTokLiveClient = tikTokLiveClient; + this.messagesHandler = messageHandler; + this.eventHandler = tikTokEventHandler; + this.liveClient = tikTokLiveClient; } @Override @@ -61,7 +60,7 @@ public class TikTokWebSocketListener extends WebSocketClient { try { handleBinary(bytes.array()); } catch (Exception e) { - tikTokEventHandler.publish(tikTokLiveClient, new TikTokErrorEvent(e)); + eventHandler.publish(liveClient, new TikTokErrorEvent(e)); } if (isOpen()) { sendPing(); @@ -85,12 +84,12 @@ public class TikTokWebSocketListener extends WebSocketClient { this.send(pushFrameBuilder.build().toByteArray()); } } - messageHandler.handle(tikTokLiveClient, webcastResponse); + messagesHandler.handle(liveClient, webcastResponse); } @Override public void onOpen(ServerHandshake serverHandshake) { - tikTokEventHandler.publish(tikTokLiveClient, new TikTokConnectedEvent()); + eventHandler.publish(liveClient, new TikTokConnectedEvent()); if (isOpen()) { sendPing(); } @@ -98,13 +97,13 @@ public class TikTokWebSocketListener extends WebSocketClient { @Override public void onClose(int code, String reason, boolean remote) { - tikTokEventHandler.publish(tikTokLiveClient, new TikTokDisconnectedEvent(reason)); - tikTokLiveClient.disconnect(); + eventHandler.publish(liveClient, new TikTokDisconnectedEvent(reason)); + liveClient.disconnect(); } @Override public void onError(Exception error) { - tikTokEventHandler.publish(tikTokLiveClient, new TikTokErrorEvent(error)); + eventHandler.publish(liveClient, new TikTokErrorEvent(error)); if (isOpen()) { sendPing(); } @@ -132,6 +131,7 @@ public class TikTokWebSocketListener extends WebSocketClient { @Override public void onMessage(String s) { - // System.err.println(s); + //TODO we are not using this method, however I wounder if there might be + //so messages that are send as String from TikTok, for example some Jsons } } \ No newline at end of file diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketOfflineClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketOfflineClient.java index 993491b..496b7ef 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketOfflineClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketOfflineClient.java @@ -22,14 +22,13 @@ */ package io.github.jwdeveloper.tiktok.websocket; -import io.github.jwdeveloper.tiktok.TikTokLiveEventHandler; import io.github.jwdeveloper.tiktok.data.events.TikTokConnectedEvent; import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent; import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData; import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveEventsHandler; -public class TikTokWebSocketOfflineClient implements SocketClient { +public class TikTokWebSocketOfflineClient implements LiveSocketClient { private final LiveEventsHandler handler; private LiveClient liveClient; diff --git a/Client/src/test/java/io/github/jwdeveloper/tiktok/TikTokLiveClientTests.java b/Client/src/test/java/io/github/jwdeveloper/tiktok/TikTokLiveClientTests.java new file mode 100644 index 0000000..0b5026f --- /dev/null +++ b/Client/src/test/java/io/github/jwdeveloper/tiktok/TikTokLiveClientTests.java @@ -0,0 +1,51 @@ +package io.github.jwdeveloper.tiktok; + +import io.github.jwdeveloper.dependance.implementation.DependanceContainerBuilder; +import io.github.jwdeveloper.tiktok.data.events.TikTokConnectedEvent; +import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent; +import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent; +import io.github.jwdeveloper.tiktok.data.events.control.TikTokConnectingEvent; +import io.github.jwdeveloper.tiktok.data.events.control.TikTokPreConnectionEvent; +import io.github.jwdeveloper.tiktok.data.events.http.TikTokRoomDataResponseEvent; +import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent; +import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; +import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder; +import io.github.jwdeveloper.tiktok.models.ConnectionState; +import org.junit.Assert; +import org.junit.Test; + +public class TikTokLiveClientTests extends TikTokTestBase { + + @Override + public void onBeforeEachTest(LiveClientBuilder liveClientBuilder, + DependanceContainerBuilder containerBuilder) { + + + } + + @Test + public void shouldThrownWhenAlreadyConnected() { + roomInfoMock().setConnectionState(ConnectionState.CONNECTED); + Assert.assertThrows(TikTokLiveException.class, () -> + { + liveClient().connect(); + }); + Assert.assertEquals(ConnectionState.DISCONNECTED, roomInfoMock().getConnectionState()); + AssertEvents( + TikTokErrorEvent.class, + TikTokDisconnectedEvent.class + ); + } + + @Test + public void shouldConnect() { + liveClient().connect(); + Assert.assertEquals(ConnectionState.CONNECTED, roomInfoMock().getConnectionState()); + AssertEvents( + TikTokConnectingEvent.class, + TikTokRoomDataResponseEvent.class, + TikTokPreConnectionEvent.class, + TikTokConnectedEvent.class, + TikTokRoomInfoEvent.class); + } +} diff --git a/Client/src/test/java/io/github/jwdeveloper/tiktok/TikTokTestBase.java b/Client/src/test/java/io/github/jwdeveloper/tiktok/TikTokTestBase.java new file mode 100644 index 0000000..af6e434 --- /dev/null +++ b/Client/src/test/java/io/github/jwdeveloper/tiktok/TikTokTestBase.java @@ -0,0 +1,53 @@ +package io.github.jwdeveloper.tiktok; + +import io.github.jwdeveloper.dependance.implementation.DependanceContainerBuilder; +import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; +import io.github.jwdeveloper.tiktok.live.LiveClient; +import io.github.jwdeveloper.tiktok.live.LiveEventsHandler; +import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder; +import io.github.jwdeveloper.tiktok.mocks.EventsHandlerMock; +import lombok.Getter; +import lombok.experimental.Accessors; +import org.junit.Before; + +/** + * Base class for the unit tests + */ + +@Getter +@Accessors(fluent = true) +public abstract class TikTokTestBase { + + private LiveClient liveClient; + + private EventsHandlerMock eventsHandlerMock; + + private TikTokRoomInfo roomInfoMock; + + public void AssertEvents(Class... events) { + eventsHandlerMock.assertEvents(events); + } + + @Before + public void setup() { + + var builder = TikTokLive.newClient("test"); + eventsHandlerMock = new EventsHandlerMock(); + roomInfoMock = new TikTokRoomInfo(); + roomInfoMock.setHostName("test"); + liveClient = builder + .configure(liveClientSettings -> + { + liveClientSettings.setOffline(true); + liveClientSettings.setFetchGifts(false); + }) + .customize(containerBuilder -> + { + containerBuilder.registerSingleton(LiveEventsHandler.class, eventsHandlerMock); + containerBuilder.registerSingleton(TikTokRoomInfo.class, roomInfoMock); + onBeforeEachTest(builder, containerBuilder); + }).build(); + } + + public abstract void onBeforeEachTest(LiveClientBuilder liveClientBuilder, DependanceContainerBuilder containerBuilder); +} diff --git a/Client/src/test/java/io/github/jwdeveloper/tiktok/listener/TikTokListenersManagerTest.java b/Client/src/test/java/io/github/jwdeveloper/tiktok/listener/TikTokListenersManagerTest.java index 5fe8df1..915bcfe 100644 --- a/Client/src/test/java/io/github/jwdeveloper/tiktok/listener/TikTokListenersManagerTest.java +++ b/Client/src/test/java/io/github/jwdeveloper/tiktok/listener/TikTokListenersManagerTest.java @@ -22,7 +22,10 @@ */ package io.github.jwdeveloper.tiktok.listener; +import io.github.jwdeveloper.dependance.Dependance; +import io.github.jwdeveloper.dependance.api.DependanceContainer; import io.github.jwdeveloper.tiktok.TikTokLiveEventHandler; +import io.github.jwdeveloper.tiktok.annotations.Priority; import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent; @@ -44,27 +47,34 @@ class TikTokListenersManagerTest { private TikTokLiveEventHandler eventObserver; private TikTokListenersManager tikTokListenersManager; + private DependanceContainer dependanceContainer; + private LiveClient liveClient; @BeforeEach void setUp() { - eventObserver = Mockito.mock(TikTokLiveEventHandler.class); - List listeners = new ArrayList<>(); - tikTokListenersManager = new TikTokListenersManager(listeners, eventObserver); + + liveClient = Mockito.mock(LiveClient.class); + eventObserver = new TikTokLiveEventHandler(); + + dependanceContainer = Dependance.newContainer() + .registerSingleton(LiveClient.class, liveClient) + .build(); + tikTokListenersManager = new TikTokListenersManager(eventObserver, dependanceContainer); } @Test void addListener() { - TikTokEventListener listener =new TikTokEventListenerTest(); + Object listener = new TikTokEventListenerTest(); tikTokListenersManager.addListener(listener); - List listeners = tikTokListenersManager.getListeners(); + List listeners = tikTokListenersManager.getListeners(); assertEquals(1, listeners.size()); assertSame(listener, listeners.get(0)); } @Test void addListener_alreadyRegistered_throwsException() { - TikTokEventListener listener = new TikTokEventListenerTest(); + Object listener = new TikTokEventListenerTest(); tikTokListenersManager.addListener(listener); Exception exception = assertThrows(TikTokLiveException.class, () -> { @@ -76,39 +86,56 @@ class TikTokListenersManagerTest { @Test void removeListener() { - TikTokEventListener listener = new TikTokEventListenerTest(); + Object listener = new TikTokEventListenerTest(); tikTokListenersManager.addListener(listener); tikTokListenersManager.removeListener(listener); - List listeners = tikTokListenersManager.getListeners(); + List listeners = tikTokListenersManager.getListeners(); assertTrue(listeners.isEmpty()); } + @Test + public void shouldTriggerEvents() { + + Object listener = new TikTokEventListenerTest(); + tikTokListenersManager.addListener(listener); + + + var fakeGiftEvent = TikTokGiftEvent.of("TestRosa", 1, 1); + eventObserver.publish(liveClient, fakeGiftEvent); + } + @Test void removeListener_notRegistered_doesNotThrow() { - TikTokEventListener listener = new TikTokEventListenerTest(); + Object listener = new TikTokEventListenerTest(); assertDoesNotThrow(() -> tikTokListenersManager.removeListener(listener)); } - public static class TikTokEventListenerTest implements TikTokEventListener - { + public static class TikTokEventListenerTest { @TikTokEventObserver - public void onJoin(LiveClient client, TikTokJoinEvent joinEvent) - { - + public void onJoin(LiveClient client, TikTokJoinEvent joinEvent) { + System.out.println("Hello from on join" + client + " " + joinEvent); } - @TikTokEventObserver - public void onGift(LiveClient client, TikTokGiftEvent giftMessageEvent) - { - + @TikTokEventObserver(priority = Priority.LOWEST) + public void onGift(LiveClient client, TikTokGiftEvent giftMessageEvent) { + System.out.println("Hello from onGift lowest priority" + client + " " + giftMessageEvent); } - @TikTokEventObserver - public void onEvent(LiveClient client, TikTokEvent event) - { + @TikTokEventObserver(priority = Priority.NORMAL) + public void onGift2(LiveClient client, TikTokGiftEvent giftMessageEvent) { + System.out.println("Hello from onGift normal priority " + client + " " + giftMessageEvent); + } + @TikTokEventObserver(priority = Priority.HIGHEST) + public void onGift3(LiveClient client, TikTokGiftEvent giftMessageEvent) { + System.out.println("Hello from onGift highest priority " + client + " " + giftMessageEvent); + } + + @TikTokEventObserver(async = true) + public void onEvent(LiveClient client, TikTokEvent event) { + System.out.println("Hello from onEvent im running on the thread " + Thread.currentThread().getName()); } } } \ No newline at end of file diff --git a/Client/src/test/java/io/github/jwdeveloper/tiktok/mocks/EventsHandlerMock.java b/Client/src/test/java/io/github/jwdeveloper/tiktok/mocks/EventsHandlerMock.java new file mode 100644 index 0000000..e1123c2 --- /dev/null +++ b/Client/src/test/java/io/github/jwdeveloper/tiktok/mocks/EventsHandlerMock.java @@ -0,0 +1,46 @@ +package io.github.jwdeveloper.tiktok.mocks; + +import io.github.jwdeveloper.tiktok.TikTokLiveEventHandler; +import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; +import io.github.jwdeveloper.tiktok.live.LiveClient; + +import java.util.ArrayList; +import java.util.List; + +/** + * Cache published events, + */ +public class EventsHandlerMock extends TikTokLiveEventHandler { + private final List publishedEvents = new ArrayList(); + + + @Override + public void publish(LiveClient tikTokLiveClient, TikTokEvent tikTokEvent) { + super.publish(tikTokLiveClient, tikTokEvent); + publishedEvents.add(tikTokEvent); + } + + @SafeVarargs + public final void assertEvents(Class... events) { + + if (events.length == 0 && !publishedEvents.isEmpty()) { + var classNames = publishedEvents.stream() + .map(e -> e.getClass().getSimpleName()) + .toList(); + var invokedEvents = String.join("\n", classNames); + throw new IllegalArgumentException("Not events should be invoked but there was: \n" + invokedEvents); + } + + + for (var i = 0; i < events.length; i++) { + var expectedEvent = events[i]; + var invokedEvent = publishedEvents.get(i); + if (expectedEvent.equals(invokedEvent.getClass())) { + continue; + } + throw new RuntimeException("Expected event was " + expectedEvent + " but acctuall was " + invokedEvent.getClass()); + } + + + } +} diff --git a/Examples/pom.xml b/examples/pom.xml similarity index 98% rename from Examples/pom.xml rename to examples/pom.xml index 8d43913..2e17d14 100644 --- a/Examples/pom.xml +++ b/examples/pom.xml @@ -46,7 +46,7 @@ 4.0.0 - Examples + examples io.github.jwdeveloper.tiktok diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/CollectorExample.java b/examples/src/main/java/io/github/jwdeveloper/tiktok/CollectorExample.java similarity index 100% rename from Examples/src/main/java/io/github/jwdeveloper/tiktok/CollectorExample.java rename to examples/src/main/java/io/github/jwdeveloper/tiktok/CollectorExample.java diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/ConnectionExample.java b/examples/src/main/java/io/github/jwdeveloper/tiktok/ConnectionExample.java similarity index 99% rename from Examples/src/main/java/io/github/jwdeveloper/tiktok/ConnectionExample.java rename to examples/src/main/java/io/github/jwdeveloper/tiktok/ConnectionExample.java index b9e70e5..c7226af 100644 --- a/Examples/src/main/java/io/github/jwdeveloper/tiktok/ConnectionExample.java +++ b/examples/src/main/java/io/github/jwdeveloper/tiktok/ConnectionExample.java @@ -37,9 +37,6 @@ public class ConnectionExample { public static void main(String[] args) throws IOException { showLogo(); - - var gifts = TikTokLive.gifts(); - TikTokLive.newClient(ConnectionExample.TIKTOK_HOSTNAME) .configure(clientSettings -> { diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/CustomEventExample.java b/examples/src/main/java/io/github/jwdeveloper/tiktok/CustomEventExample.java similarity index 100% rename from Examples/src/main/java/io/github/jwdeveloper/tiktok/CustomEventExample.java rename to examples/src/main/java/io/github/jwdeveloper/tiktok/CustomEventExample.java diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/CustomMappingExample.java b/examples/src/main/java/io/github/jwdeveloper/tiktok/CustomMappingExample.java similarity index 99% rename from Examples/src/main/java/io/github/jwdeveloper/tiktok/CustomMappingExample.java rename to examples/src/main/java/io/github/jwdeveloper/tiktok/CustomMappingExample.java index 05fe752..ce3c853 100644 --- a/Examples/src/main/java/io/github/jwdeveloper/tiktok/CustomMappingExample.java +++ b/examples/src/main/java/io/github/jwdeveloper/tiktok/CustomMappingExample.java @@ -30,7 +30,7 @@ public class CustomMappingExample { public static void main(String[] args) { TikTokLive.newClient("saszareznikow") - .onMapping(mapper -> + .mappings(mapper -> { mapper.forMessage(WebcastChatMessage.class) .onBeforeMapping((inputBytes, messageName, mapperHelper) -> @@ -56,7 +56,6 @@ public class CustomMappingExample { System.out.println("onAfter mapping, " + source.getClass().getSimpleName() + " was mapped to " + events.size() + " events"); return events; }); - /* There might be cast that we don't have Webcast class for incoming message from TikTok `mapperHelper.bytesToProtoBufferStructure` but you can still investigate message structure diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/CustomizationExample.java b/examples/src/main/java/io/github/jwdeveloper/tiktok/CustomizationExample.java similarity index 100% rename from Examples/src/main/java/io/github/jwdeveloper/tiktok/CustomizationExample.java rename to examples/src/main/java/io/github/jwdeveloper/tiktok/CustomizationExample.java diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/Events_And_Gifts_Testing_Example.java b/examples/src/main/java/io/github/jwdeveloper/tiktok/Events_And_Gifts_Testing_Example.java similarity index 100% rename from Examples/src/main/java/io/github/jwdeveloper/tiktok/Events_And_Gifts_Testing_Example.java rename to examples/src/main/java/io/github/jwdeveloper/tiktok/Events_And_Gifts_Testing_Example.java diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/GiftsExample.java b/examples/src/main/java/io/github/jwdeveloper/tiktok/GiftsExample.java similarity index 99% rename from Examples/src/main/java/io/github/jwdeveloper/tiktok/GiftsExample.java rename to examples/src/main/java/io/github/jwdeveloper/tiktok/GiftsExample.java index bd56d3d..732f436 100644 --- a/Examples/src/main/java/io/github/jwdeveloper/tiktok/GiftsExample.java +++ b/examples/src/main/java/io/github/jwdeveloper/tiktok/GiftsExample.java @@ -29,8 +29,6 @@ public class GiftsExample { public static void main(String[] args) { var giftsManager = TikTokLive.gifts(); - - var giftsList = giftsManager.toList(); for (var gift : giftsList) { System.out.println("Gift: " + gift); diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/ListenerExample.java b/examples/src/main/java/io/github/jwdeveloper/tiktok/ListenerExample.java similarity index 79% rename from Examples/src/main/java/io/github/jwdeveloper/tiktok/ListenerExample.java rename to examples/src/main/java/io/github/jwdeveloper/tiktok/ListenerExample.java index d12111e..09706b1 100644 --- a/Examples/src/main/java/io/github/jwdeveloper/tiktok/ListenerExample.java +++ b/examples/src/main/java/io/github/jwdeveloper/tiktok/ListenerExample.java @@ -28,21 +28,18 @@ import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent; import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent; -import io.github.jwdeveloper.tiktok.listener.TikTokEventListener; import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.utils.ConsoleColors; import java.io.IOException; -public class ListenerExample -{ +public class ListenerExample { // + /** - * - * Listeners are an alternative way of handling events. - * I would to suggest to use then when logic of handing event - * is more complex - * + * Listeners are an alternative way of handling events. + * I would to suggest to use then when logic of handing event + * is more complex */ public static void main(String[] args) throws IOException { showLogo(); @@ -55,24 +52,21 @@ public class ListenerExample } /** - * - * Method in TikTokEventListener should meet 4 requirements to be detected - * - must have @TikTokEventObserver annotation - * - must have 2 parameters - * - first parameter must be LiveClient - * - second must be class that extending TikTokEvent + * Method must meet 2 requirements to be detected + * - must have @TikTokEventObserver annotation + * - must have 1 parameter of type that extending TikTokEvent */ - public static class CustomListener implements TikTokEventListener { + public static class CustomListener { @TikTokEventObserver - public void onLike(LiveClient liveClient, TikTokLikeEvent event) { + public void onLike(TikTokLikeEvent event) { System.out.println(event.toString()); } @TikTokEventObserver - public void onError(LiveClient liveClient, TikTokErrorEvent event) { - // event.getException().printStackTrace(); + public void onError(TikTokErrorEvent event, LiveClient liveClient) { + // event.getException().printStackTrace(); } @TikTokEventObserver @@ -103,9 +97,8 @@ public class ListenerExample } // - private static void showLogo() - { - System.out.println(ConsoleColors.GREEN+""" + private static void showLogo() { + System.out.println(ConsoleColors.GREEN + """ _____ _ _ _____ _ _ _ \s |_ _(_) | _|_ _|__ | | _| | (_)_ _____\s diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/ProxyExample.java b/examples/src/main/java/io/github/jwdeveloper/tiktok/ProxyExample.java similarity index 100% rename from Examples/src/main/java/io/github/jwdeveloper/tiktok/ProxyExample.java rename to examples/src/main/java/io/github/jwdeveloper/tiktok/ProxyExample.java diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/RecorderExample.java b/examples/src/main/java/io/github/jwdeveloper/tiktok/RecorderExample.java similarity index 99% rename from Examples/src/main/java/io/github/jwdeveloper/tiktok/RecorderExample.java rename to examples/src/main/java/io/github/jwdeveloper/tiktok/RecorderExample.java index 9c10e7b..6ce4c2e 100644 --- a/Examples/src/main/java/io/github/jwdeveloper/tiktok/RecorderExample.java +++ b/examples/src/main/java/io/github/jwdeveloper/tiktok/RecorderExample.java @@ -32,6 +32,7 @@ public class RecorderExample { public static void main(String[] args) { + TikTokLive.newClient("bangbetmenygy") .configure(liveClientSettings -> { diff --git a/future.md b/future.md new file mode 100644 index 0000000..4f8f9fc --- /dev/null +++ b/future.md @@ -0,0 +1,7 @@ +Future plans: + +[ ] Publish project to Maven repository instead of JITPACK +[ ] Dynamically generates readme.md when new version is released +[ ] Covers all possible classes from Client module with unit test +[ ] Add tests check to GitHub publish action +[ ] Generates documentation based on API module and publish it with GitHub pages diff --git a/pom.xml b/pom.xml index 07e272e..886687c 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ API Client - Examples + examples tools-readme extension-recorder diff --git a/tools-readme/pom.xml b/tools-readme/pom.xml index 59ce99b..6ef4a8e 100644 --- a/tools-readme/pom.xml +++ b/tools-readme/pom.xml @@ -34,12 +34,6 @@ 2.13.0 compile - - com.github.jwdeveloper.Descrabble - Descrabble-Full - 0.0.11-Release - compile - org.reflections reflections diff --git a/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/EventsDecorator.java b/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/EventsDecorator.java deleted file mode 100644 index 441bdb9..0000000 --- a/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/EventsDecorator.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.jwdeveloper.tiktok; - -import io.github.jwdeveloper.descrabble.api.DescriptionDecorator; -import io.github.jwdeveloper.descrabble.api.elements.Element; -import io.github.jwdeveloper.descrabble.api.elements.ElementFactory; - -public class EventsDecorator implements DescriptionDecorator { - - - - - @Override - public void decorate(Element root, ElementFactory factory) - { - - } -} diff --git a/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/EventsInfoGenerator.java b/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/EventsInfoGenerator.java index eb6f398..6ad3c6b 100644 --- a/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/EventsInfoGenerator.java +++ b/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/EventsInfoGenerator.java @@ -41,7 +41,6 @@ public class EventsInfoGenerator { System.out.println(res); } - public String run() { var events = getEventsDtos(); var builder = new StringBuilder(); diff --git a/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/Main.java b/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/Main.java index 7968d22..07a79b2 100644 --- a/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/Main.java +++ b/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/Main.java @@ -1,8 +1,6 @@ package io.github.jwdeveloper.tiktok; -import io.github.jwdeveloper.descrabble.api.DescriptionGenerator; -import io.github.jwdeveloper.descrabble.framework.Descrabble; -import io.github.jwdeveloper.descrabble.plugin.github.DescrabbleGithub; + import org.apache.commons.io.FileUtils; import java.io.File; @@ -23,16 +21,6 @@ public class Main var output = System.getProperty("user.dir"); - DescriptionGenerator generator = Descrabble.create() - .withTemplate(targetFile) - .withVariable("version", version) - .withDecorator(new EventsDecorator()) - .withPlugin(DescrabbleGithub.plugin("README.md")) - .build(); - - generator.generate(output); - targetFile.delete(); - inputStream.close(); } } diff --git a/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/ReadmeGenerator.java b/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/ReadmeGenerator.java index 19413c6..04856a8 100644 --- a/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/ReadmeGenerator.java +++ b/tools-readme/src/main/java/io/github/jwdeveloper/tiktok/ReadmeGenerator.java @@ -27,7 +27,6 @@ public class ReadmeGenerator { public static void main(String[] args) { var generator = new ReadmeGenerator(); generator.generate(); - } public void generate() { diff --git a/tools-readme/src/main/resources/template.md b/tools-readme/src/main/resources/template.md index c496dad..e94236f 100644 --- a/tools-readme/src/main/resources/template.md +++ b/tools-readme/src/main/resources/template.md @@ -88,8 +88,6 @@ Do you prefer other programming languages? {{if item is 2}} -my name is {{item.name}} - {{else}} {{end}} @@ -98,7 +96,6 @@ my name is {{item.name}}
## Listeners - ```java {{listener-content}} ```