From 046d5f17566f9d17c2e2d571075f037a4cda3879 Mon Sep 17 00:00:00 2001 From: "jacek.wolniewicz" Date: Mon, 1 Jul 2024 21:25:30 +0200 Subject: [PATCH] Simplify adding events to TikTok Builder, checkout `EventsBuilder` --- .../tiktok/live/builder/EventsBuilder.java | 116 ++++-- .../tiktok/TikTokLiveClientBuilder.java | 360 +----------------- Tools-ReadmeGenerator/pom.xml | 8 +- .../jwdeveloper/tiktok/EventsDecorator.java | 12 + .../io/github/jwdeveloper/tiktok/Main.java | 37 ++ .../jwdeveloper/tiktok/ReadmeGenerator.java | 6 +- .../src/main/resources/readme-template.html | 66 ++++ 7 files changed, 216 insertions(+), 389 deletions(-) create mode 100644 Tools-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/EventsDecorator.java create mode 100644 Tools-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/Main.java create mode 100644 Tools-ReadmeGenerator/src/main/resources/readme-template.html diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/EventsBuilder.java b/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/EventsBuilder.java index c5dfb7a..961ff49 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/EventsBuilder.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/EventsBuilder.java @@ -22,8 +22,8 @@ */ package io.github.jwdeveloper.tiktok.live.builder; -import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.*; +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.gift.TikTokGiftComboEvent; import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent; @@ -55,7 +55,9 @@ public interface EventsBuilder { * @param action consumable action * @return self instance */ - T onEvent(EventConsumer action); + default T onEvent(EventConsumer action) { + return onEvent(TikTokEvent.class, action); + } /** * Invoked when information about room (live) got updated such as viewer count, etc.. @@ -63,113 +65,171 @@ public interface EventsBuilder { * @param action consumable action * @return self instance */ - T onRoomInfo(EventConsumer action); + default T onRoomInfo(EventConsumer action) { + return onEvent(TikTokRoomInfoEvent.class, action); + } /** * Invoked when someone send message to chat + * * @param action consumable action * @return self instance */ - T onComment(EventConsumer action); + default T onComment(EventConsumer action) { + return onEvent(TikTokCommentEvent.class, action); + } /** * Invoked when TikTokLiveJava makes http request and getting response + * * @param action consumable action * @return self instance */ - T onHttpResponse(EventConsumer action); + default T onHttpResponse(EventConsumer action) { + return onEvent(TikTokHttpResponseEvent.class, action); + } /** * Invoked when TikTok protocolBuffer data "message" was successfully mapped to event * events contains protocol-buffer "Message" and TikTokLiveJava "Event" + * * @param action consumable action * @return self instance */ - T onWebsocketMessage(EventConsumer action); + default T onWebsocketMessage(EventConsumer action) { + return onEvent(TikTokWebsocketMessageEvent.class, action); + } /** * Invoked when there was not found event mapper for TikTok protocolBuffer data "message" + * * @param action consumable action * @return self instance */ - T onWebsocketUnhandledMessage(EventConsumer action); + default T onWebsocketUnhandledMessage(EventConsumer action) { + return onEvent(TikTokWebsocketUnhandledMessageEvent.class, action); + } /** * Invoked every time TikTok sends protocolBuffer data to websocket * Response contains list of messages that are later mapped to events + * * @param action consumable action * @return self instance */ - T onWebsocketResponse(EventConsumer action); + default T onWebsocketResponse(EventConsumer action) { + return onEvent(TikTokWebsocketResponseEvent.class, action); + } /** * Invoked for gifts that has no combo, or when combo finishes + * * @param action consumable action * @return self instance */ - T onGift(EventConsumer action); + default T onGift(EventConsumer action) { + return onEvent(TikTokGiftEvent.class, action); + } /** * Invoked for gifts that has combo options such as roses + * * @param action consumable action * @return self instance */ - T onGiftCombo(EventConsumer action); + default T onGiftCombo(EventConsumer action) { + return onEvent(TikTokGiftComboEvent.class, action); + } - T onQuestion(EventConsumer action); + default T onQuestion(EventConsumer action) { + return onEvent(TikTokQuestionEvent.class, action); + } - T onSubscribe(EventConsumer action); + default T onSubscribe(EventConsumer action) { + return onEvent(TikTokSubscribeEvent.class, action); + } - T onFollow(EventConsumer action); + default T onFollow(EventConsumer action) { + return onEvent(TikTokFollowEvent.class, action); + } - T onLike(EventConsumer action); + default T onLike(EventConsumer action) { + return onEvent(TikTokLikeEvent.class, action); + } - T onEmote(EventConsumer action); + default T onEmote(EventConsumer action) { + return onEvent(TikTokEmoteEvent.class, action); + } - T onJoin(EventConsumer action); + default T onJoin(EventConsumer action) { + return onEvent(TikTokJoinEvent.class, action); + } - T onShare(EventConsumer action); + default T onShare(EventConsumer action) { + return onEvent(TikTokShareEvent.class, action); + } - T onLivePaused(EventConsumer action); + default T onLivePaused(EventConsumer action) { + return onEvent(TikTokLivePausedEvent.class, action); + } - T onLiveUnpaused(EventConsumer action); + default T onLiveUnpaused(EventConsumer action) { + return onEvent(TikTokLiveUnpausedEvent.class, action); + } - T onLiveEnded(EventConsumer action); + default T onLiveEnded(EventConsumer action) { + return onEvent(TikTokLiveEndedEvent.class, action); + } /** * Invoked when client has been successfully connected to live + * * @param action consumable action * @return self instance */ - T onConnected(EventConsumer action); + default T onConnected(EventConsumer action) { + return onEvent(TikTokConnectedEvent.class, action); + } /** * Invoked before client has been successfully connected to live + * * @param action consumable action * @return self instance */ - T onPreConnection(EventConsumer action); + default T onPreConnection(EventConsumer action) { + return onEvent(TikTokPreConnectionEvent.class, action); + } /** * Invoked when client tries to reconnect + * * @param action consumable action * @return self instance */ - T onReconnecting(EventConsumer action); + default T onReconnecting(EventConsumer action) { + return onEvent(TikTokReconnectingEvent.class, action); + } /** * Invoked when client disconnected + * * @param action consumable action * @return self instance */ - T onDisconnected(EventConsumer action); + default T onDisconnected(EventConsumer action) { + return onEvent(TikTokDisconnectedEvent.class, action); + } /** * Invoked when exception was throed inside client or event handler + * * @param action consumable action * @return self instance */ - T onError(EventConsumer action); + default T onError(EventConsumer action) { + return onEvent(TikTokErrorEvent.class, action); + } // TODO Figure out how those events works @@ -216,4 +276,10 @@ public interface EventsBuilder { //T onLinkMicBattle(TikTokEventConsumer event); //T onUnhandledControl(TikTokEventConsumer event); + + /** + * To do figure out how to use Annotation processor. + * Goal is to generates methods for all possible events, everytime library is compiled + */ + } \ 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 1f2b7ce..f8a19ff 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java @@ -189,365 +189,9 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder { return build().connectAsync(); } - /** - * To do figure out how to use Annotation processor. - * Goal is to generates methods for all possible events, everytime library is compiled - */ - public TikTokLiveClientBuilder onUnhandledSocial(EventConsumer event) { - eventHandler.subscribe(TikTokUnhandledSocialEvent.class, event); - return this; - } - - public LiveClientBuilder onChest(EventConsumer event) { - eventHandler.subscribe(TikTokChestEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkMicFanTicket(EventConsumer event) { - eventHandler.subscribe(TikTokLinkMicFanTicketEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onEnvelope(EventConsumer event) { - eventHandler.subscribe(TikTokEnvelopeEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onShop(EventConsumer event) { - eventHandler.subscribe(TikTokShopEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onDetect(EventConsumer event) { - eventHandler.subscribe(TikTokDetectEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkLayer(EventConsumer event) { - eventHandler.subscribe(TikTokLinkLayerEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onConnected(EventConsumer event) { - eventHandler.subscribe(TikTokConnectedEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onPreConnection(EventConsumer event) { - eventHandler.subscribe(TikTokPreConnectionEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onCaption(EventConsumer event) { - eventHandler.subscribe(TikTokCaptionEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onQuestion(EventConsumer event) { - eventHandler.subscribe(TikTokQuestionEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onRoomPin(EventConsumer event) { - eventHandler.subscribe(TikTokRoomPinEvent.class, event); - return this; - } - @Override - public LiveClientBuilder onEvent(Class eventClass, EventConsumer event) { - eventHandler.subscribe(eventClass, event); - return this; - } - - @Override - public TikTokLiveClientBuilder onRoomInfo(EventConsumer event) { - eventHandler.subscribe(TikTokRoomInfoEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLivePaused(EventConsumer event) { - eventHandler.subscribe(TikTokLivePausedEvent.class, event); - return this; - } - - @Override - public TikTokLiveClientBuilder onLiveUnpaused(EventConsumer event) { - eventHandler.subscribe(TikTokLiveUnpausedEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLike(EventConsumer event) { - eventHandler.subscribe(TikTokLikeEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLink(EventConsumer event) { - eventHandler.subscribe(TikTokLinkEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkInvite(EventConsumer event) { - eventHandler.subscribe(TikTokLinkInviteEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkReply(EventConsumer event) { - eventHandler.subscribe(TikTokLinkReplyEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkCreate(EventConsumer event) { - eventHandler.subscribe(TikTokLinkCreateEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkClose(EventConsumer event) { - eventHandler.subscribe(TikTokLinkCloseEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkEnter(EventConsumer event) { - eventHandler.subscribe(TikTokLinkEnterEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkLeave(EventConsumer event) { - eventHandler.subscribe(TikTokLinkLeaveEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkCancel(EventConsumer event) { - eventHandler.subscribe(TikTokLinkCancelEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkKickOut(EventConsumer event) { - eventHandler.subscribe(TikTokLinkKickOutEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkLinkedListChange(EventConsumer event) { - eventHandler.subscribe(TikTokLinkLinkedListChangeEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkUpdateUser(EventConsumer event) { - eventHandler.subscribe(TikTokLinkUpdateUserEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkWaitListChange(EventConsumer event) { - eventHandler.subscribe(TikTokLinkWaitListChangeEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkMute(EventConsumer event) { - eventHandler.subscribe(TikTokLinkMuteEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkRandomMatch(EventConsumer event) { - eventHandler.subscribe(TikTokLinkRandomMatchEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkUpdateUserSettings(EventConsumer event) { - eventHandler.subscribe(TikTokLinkUpdateUserSettingEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkMicIdxUpdate(EventConsumer event) { - eventHandler.subscribe(TikTokLinkMicIdxUpdateEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkListChange(EventConsumer event) { - eventHandler.subscribe(TikTokLinkListChangeEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkCohostListChange(EventConsumer event) { - eventHandler.subscribe(TikTokLinkCohostListChangeEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkMediaChange(EventConsumer event) { - eventHandler.subscribe(TikTokLinkMediaChangeEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkAcceptNotice(EventConsumer event) { - eventHandler.subscribe(TikTokLinkAcceptNoticeEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkSysKickOut(EventConsumer event) { - eventHandler.subscribe(TikTokLinkSysKickOutEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkUserToast(EventConsumer event) { - eventHandler.subscribe(TikTokLinkUserToastEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onBarrage(EventConsumer event) { - eventHandler.subscribe(TikTokBarrageEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onGift(EventConsumer event) { - eventHandler.subscribe(TikTokGiftEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onGiftCombo(EventConsumer event) { - eventHandler.subscribe(TikTokGiftComboEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkMicArmies(EventConsumer event) { - eventHandler.subscribe(TikTokLinkMicArmiesEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onEmote(EventConsumer event) { - eventHandler.subscribe(TikTokEmoteEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onUnauthorizedMember(EventConsumer event) { - eventHandler.subscribe(TikTokUnauthorizedMemberEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onInRoomBanner(EventConsumer event) { - eventHandler.subscribe(TikTokInRoomBannerEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkMicMethod(EventConsumer event) { - eventHandler.subscribe(TikTokLinkMicMethodEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onSubscribe(EventConsumer event) { - eventHandler.subscribe(TikTokSubscribeEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onPoll(EventConsumer event) { - eventHandler.subscribe(TikTokPollEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onFollow(EventConsumer event) { - eventHandler.subscribe(TikTokFollowEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onComment(EventConsumer event) { - eventHandler.subscribe(TikTokCommentEvent.class, event); - return this; - } - - @Override - public LiveClientBuilder onHttpResponse(EventConsumer action) { - eventHandler.subscribe(TikTokHttpResponseEvent.class, action); - return this; - } - - public TikTokLiveClientBuilder onGoalUpdate(EventConsumer event) { - eventHandler.subscribe(TikTokGoalUpdateEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onRankUpdate(EventConsumer event) { - eventHandler.subscribe(TikTokRankUpdateEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onIMDelete(EventConsumer event) { - eventHandler.subscribe(TikTokIMDeleteEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLiveEnded(EventConsumer event) { - eventHandler.subscribe(TikTokLiveEndedEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onError(EventConsumer event) { - eventHandler.subscribe(TikTokErrorEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onJoin(EventConsumer event) { - eventHandler.subscribe(TikTokJoinEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onRankText(EventConsumer event) { - eventHandler.subscribe(TikTokRankTextEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onShare(EventConsumer event) { - eventHandler.subscribe(TikTokShareEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onUnhandledMember(EventConsumer event) { - eventHandler.subscribe(TikTokUnhandledMemberEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onSubNotify(EventConsumer event) { - eventHandler.subscribe(TikTokSubNotifyEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onLinkMicBattle(EventConsumer event) { - eventHandler.subscribe(TikTokLinkMicBattleEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onDisconnected(EventConsumer event) { - eventHandler.subscribe(TikTokDisconnectedEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onUnhandledControl(EventConsumer event) { - eventHandler.subscribe(TikTokUnhandledControlEvent.class, event); - return this; - } - - public TikTokLiveClientBuilder onEvent(EventConsumer event) { - eventHandler.subscribe(TikTokEvent.class, event); - return this; - } - - @Override - public TikTokLiveClientBuilder onWebsocketResponse(EventConsumer event) { - eventHandler.subscribe(TikTokWebsocketResponseEvent.class, event); - return this; - } - - @Override - public TikTokLiveClientBuilder onWebsocketMessage(EventConsumer event) { - eventHandler.subscribe(TikTokWebsocketMessageEvent.class, event); - return this; - } - - @Override - public TikTokLiveClientBuilder onWebsocketUnhandledMessage(EventConsumer event) { - eventHandler.subscribe(TikTokWebsocketUnhandledMessageEvent.class, event); - return this; - } - - @Override - public TikTokLiveClientBuilder onReconnecting(EventConsumer event) { - eventHandler.subscribe(TikTokReconnectingEvent.class, event); + public LiveClientBuilder onEvent(Class eventClass, EventConsumer action) { + eventHandler.subscribe(eventClass, action); return this; } } \ No newline at end of file diff --git a/Tools-ReadmeGenerator/pom.xml b/Tools-ReadmeGenerator/pom.xml index dacec7d..a74e215 100644 --- a/Tools-ReadmeGenerator/pom.xml +++ b/Tools-ReadmeGenerator/pom.xml @@ -23,10 +23,16 @@ + + commons-io + commons-io + 2.13.0 + compile + com.github.jwdeveloper.Descrabble Descrabble-Full - 0.0.7-Release + 0.0.11-Release compile diff --git a/Tools-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/EventsDecorator.java b/Tools-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/EventsDecorator.java new file mode 100644 index 0000000..1041f33 --- /dev/null +++ b/Tools-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/EventsDecorator.java @@ -0,0 +1,12 @@ +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-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/Main.java b/Tools-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/Main.java new file mode 100644 index 0000000..9f987cd --- /dev/null +++ b/Tools-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/Main.java @@ -0,0 +1,37 @@ +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; +import java.io.IOException; + +public class Main +{ + public static void main(String[] args) throws IOException { + var version = System.getenv("VERSION"); + if (version == null || version.equals("")) { + version = "[Replace with current version]"; + } + + var inputStream = Main.class.getResourceAsStream("/readme-template.html"); + var targetFile = new File("temp.file"); + FileUtils.copyInputStreamToFile(inputStream, targetFile); + + 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-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/ReadmeGenerator.java b/Tools-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/ReadmeGenerator.java index b61d883..19413c6 100644 --- a/Tools-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/ReadmeGenerator.java +++ b/Tools-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/ReadmeGenerator.java @@ -51,10 +51,6 @@ public class ReadmeGenerator { return version == null ? "NOT_FOUND" : version; } - public String getCodeExample(String path) { - var content = FilesUtility.loadFileContent(path); - content = content.substring(content.indexOf("*/") + 2); - return content; - } + } diff --git a/Tools-ReadmeGenerator/src/main/resources/readme-template.html b/Tools-ReadmeGenerator/src/main/resources/readme-template.html new file mode 100644 index 0000000..09257ce --- /dev/null +++ b/Tools-ReadmeGenerator/src/main/resources/readme-template.html @@ -0,0 +1,66 @@ + + + + + + + + TikTok Live Java +
+ *❤️❤️🎁 *Connect to TikTok live in 3 lines* 🎁❤️❤️* +
+ + + + + +
+ + +
+ + + + jitpack.io + https://jitpack.io + + + + com.github.jwdeveloper.TikTok-Live-Java + Client + {{version}} + compile + + +
+ + +Lightweight dependency injection container that is both small and performance efficient + +Features +
+- [x] Injecting object via constructor +
+- [x] Method object providers +
+- [x] Class Scanner to avoid manual registration [Scanner](#autoscan) +
+- [x] You need to get [List of objects](#lists) in the constructor, no problem +
+- [x] Create [object instance](#object-instances) by yourself and register it to container! +
+- [x] Object lifetimes [SINGLETON, TRANSIENT] [see](#basic) +
+- [x] [Generic types](#generic-types) +
+- [x] [Many constructors](#manyconstructors) +
+- [x] Highly customizable, adjust container with build in [events](#events) system +
+ +Tutorial + +