dragas / birc Goto Github PK
View Code? Open in Web Editor NEWSomewhat elegant Java/Kotlin chat bot framework.
Somewhat elegant Java/Kotlin chat bot framework.
While writing an application, there might be a caveat, where developer might want to use middlewares or test callbacks to modify request. By doing so, the request might fail possibly successful tests later down the pipeline, thus a good practice should be implementing a Cloneable
interface on all Request objects.
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 188 path $.d.mention_roles[0]
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.Gson.fromJson(Gson.java:887)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.Gson.fromJson(Gson.java:852)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.Gson.fromJson(Gson.java:801)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.Gson.fromJson(Gson.java:773)
Aug 26 20:43:27 bork-236 app/worker.1: at lt.saltyjuice.dragas.chatty.v3.discord.adapter.DiscordAdapter.getFromJson(DiscordAdapter.kt:138)
Aug 26 20:43:27 bork-236 app/worker.1: at lt.saltyjuice.dragas.chatty.v3.discord.adapter.DiscordAdapter.deserialize(DiscordAdapter.kt:85)
Aug 26 20:43:27 bork-236 app/worker.1: at lt.saltyjuice.dragas.chatty.v3.discord.adapter.DiscordAdapter.decode(DiscordAdapter.kt:79)
Aug 26 20:43:27 bork-236 app/worker.1: at lt.saltyjuice.dragas.chatty.v3.discord.adapter.DiscordAdapter.decode(DiscordAdapter.kt:18)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.tyrus.core.TyrusEndpointWrapper.decodeCompleteMessage(TyrusEndpointWrapper.java:439)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.tyrus.core.TyrusSession.notifyMessageHandlers(TyrusSession.java:571)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.tyrus.core.TyrusEndpointWrapper.onMessage(TyrusEndpointWrapper.java:879)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.tyrus.core.TyrusWebSocket.onMessage(TyrusWebSocket.java:216)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.tyrus.core.frame.TextFrame.respond(TextFrame.java:139)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.tyrus.core.ProtocolHandler.process(ProtocolHandler.java:807)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.tyrus.client.TyrusClientEngine$TyrusReadHandler.handle(TyrusClientEngine.java:747)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter$ProcessTask.execute(GrizzlyClientFilter.java:476)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.tyrus.container.grizzly.client.TaskProcessor.processTask(TaskProcessor.java:114)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.tyrus.container.grizzly.client.TaskProcessor.processTask(TaskProcessor.java:91)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleRead(GrizzlyClientFilter.java:272)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
Aug 26 20:43:27 bork-236 app/worker.1: at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
Aug 26 20:43:27 bork-236 app/worker.1: at java.lang.Thread.run(Thread.java:745)
Aug 26 20:43:27 bork-236 app/worker.1: Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 188 path $.d.mention_roles[0]
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
Aug 26 20:43:27 bork-236 app/worker.1: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:213)
Aug 26 20:43:27 bork-236 app/worker.1: ... 40 more
as seen on heroku.
It appears that driver implementations each declare middlewares on their own. Instead, to prevent code WETness, it should be moved to Chatty/Core RouteBuilder
and should provide before
and after
methods, which specify what and how middlewares are added.
Right now Gradle dependency and build system does not seem to identify the main class while running JAR builds.
Currently Input
and Output
classes in Chatty/Core are abstract and not interfaces. Since they are not that complex nor do they benefit from being abstract, they can be easily refactored into being interfaces.
Sadly this will be a breaking change.
Right now setting nicknames in settings.json is redundant as they are not used.
This leads to another issue as the framework fails to use other nicknames when logging in to server which uses the currently hard coded nickname. Should this functionality come from Route
or should it be hardcoded?
Sometimes, chat implementations require triggering particular route once (for example in 3 responses that match condition). Such logic can be implemented via controller routes, but that might cause a race in multithread environment.
Production conditions seem to prove that authenticating on NOTICE AUTH
is bad, as this request is received twice. Which in turn causes USER
and NICK
commands to be sent twice.
Right now, Chatty/IRC implementations (bIRC in particular) have no tests, thus are subject to sudden API changes. Even though only controllers and middleware implementations are the things implementations should want to test, they should be present.
Since router should only find and test requests against route, it shouldn't have middlewares in it. Instead, Input
implementation should either return the request or null
, if it doesn't pass the global middleware. Same with Output
implementations. It should not accept a response, if it fails the test against specified middlewares.
With the release of chatty-core:2.0.0
there have been a lot of API changes, some of the removed, some added, some refined. chatty-irc
and chatty-websocket
should be updated to use them.
Right now to add more functionality user has to recompile the whole thing. There should be simple route generation (such as selecting response from a string array) from JSON.
Currently there's no websocket driver for the Chatty bots, Currently it's just on backlog of features.
There should be a general Controller
superclass, which declares how controllers should be defined. This would permit annotation scanning and declarative programming style. For example:
fun onAuthenticate(request : Request) : Response
...
router.add(router.builder().let {
it.callback(instance::onAuthenticate)
it.type(Command.RPL_WELCOME)
it.build()
})
Could be turned into
@Type(Command.RPL_WELCOME)
fun onAuthenticate(request: Request) : Response
or
fun onRandomRequest(request : Request) : Response?
...
router.add(router.builder().let {
it.testCallback(pattern)
it.middleware("DICEROLLAN")
it.callback(instance::onRandomRequest)
it.type(Command.PRIVMSG)
it.build()
})
Would become
@Pattern([some pattern])
@Type(Command.PRIVMSG)
@Middleware("DICEROLLAN")
fun onRandomRequest(request: Request) : Response?
In multiple type environment current checking for types is redundant and error prone. Instead it should involve lazy checking before evaluating if route's testCallback
returns true, thus instead of
val isAssignable = type.java.isAssignableFrom(request.javaClass)
val canBeInvoked = testMethod.invoke(controllerInstance, request) as Boolean
isAssignable && canBeInvoked
It should be
type.javaObjectType.isAssignableFrom(request.javaClass) && testMethod.invoke(controllerInstance, request) as Boolean
Also fixes #17
If you were to setup a client that listens for primitive values (int, float, etc) it wouldn't be able to deal with them due to current type checking.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.