vampire / command-framework Goto Github PK
View Code? Open in Web Editor NEWA generic CDI-based command framework
License: Apache License 2.0
A generic CDI-based command framework
License: Apache License 2.0
Allow restriction of a command to an arbitrary permission understood by discord (or rather javacord/jda) without having to create a custom Restriction
implementation.
Use cases will most commonly be cases where a bot command reproduces a discord (moderation) functionality and should only be made available to users that have that capability, like:
MANAGE_MESSAGES
permission.MODERATE_MEMBERS
/KICK_MEMBERS
/BAN_MEMBERS
permissionProviding a functionality like this directly in command-framework
will standardize handling. It will allow other code to better inspect the RestrictionChain and from that derive the actual permissions required - this will aid, for example, if slash commands are to be registered with the appropriate default permissions.
ADMINISTRATOR
permission being present should also be accepted (defaults to true
)RestrictedToPermission("MANAGE_MESSAGES")
or RestrictedToPermission("MANAGE_MESSAGES", acceptAdmin=false)
Such a system is not supported with the current annotation / restriction concept as far as I can see, so it will require some thought on how to properly integrate it. Maybe it could be implemented by adding a phase to hook into during creation of the commands where a user-provided bean could transform the command and for example check for custom annotations, parse them and add elements to the restriction chains - but those wouldn't play nicely with the @{All,Any,None}Of
annotations.
Note: Not applicable for v0.5.0 since quarkus uses CDI 2
Demo Project: https://github.com/Saladoc/quarkus-command-test
How to run the demo: Use the application.yml file to enable / disable commands, provide bot token either in application.yml or as a "-Dbot.token=your_token_here" argument in the run configuration.
The demo project creates a simple javacord bot, registering two commands. One is configured via annotations, making use of the default methods on the SlashCommandJavacord
interface, the other overrides the methods.
First issue: The default implementation is unable to locate the annotations, therefore failing the registration process due to the default values not supplying a valid description, which is mandatory for slash commands:
2022-06-28 22:30:58,567 ERROR [io.qua.run.Application] (Quarkus Main Thread) Failed to start application (with profile dev): java.lang.IllegalStateException: Descriptions are mandatory for slash commands, but command 'annotation_Subclass' does not have one
at net.kautler.command.util.SlashCommandBuilderProducer.lambda$createSlashCommandBuilderForCommand$5(SlashCommandBuilderProducer.java:116)
at java.base/java.util.Optional.orElseThrow(Optional.java:403)
at net.kautler.command.util.SlashCommandBuilderProducer.createSlashCommandBuilderForCommand(SlashCommandBuilderProducer.java:116)
at net.kautler.command.util.SlashCommandBuilderProducer.lambda$getSlashCommandBuilders$4(SlashCommandBuilderProducer.java:91)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.HashMap$EntrySpliterator.forEachRemaining(HashMap.java:1850)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at net.kautler.command.util.SlashCommandBuilderProducer.getSlashCommandBuilders(SlashCommandBuilderProducer.java:93)
at net.kautler.command.util.SlashCommandBuilderProducer_Subclass.getSlashCommandBuilders$$superforward1(Unknown Source)
at net.kautler.command.util.SlashCommandBuilderProducer_Subclass$$function$$1.apply(Unknown Source)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:53)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.proceed(InvocationInterceptor.java:62)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.monitor(InvocationInterceptor.java:49)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.intercept(Unknown Source)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:40)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
at net.kautler.command.util.SlashCommandBuilderProducer_Subclass.getSlashCommandBuilders(Unknown Source)
at net.kautler.command.util.SlashCommandBuilderProducer_ProducerMethod_getSlashCommandBuilders_fe96c7e672b8b38361a2d9554b9c13bcb851b3a6_Bean.create(Unknown Source)
at net.kautler.command.util.SlashCommandBuilderProducer_ProducerMethod_getSlashCommandBuilders_fe96c7e672b8b38361a2d9554b9c13bcb851b3a6_Bean.create(Unknown Source)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:111)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:35)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:32)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:32)
at io.quarkus.arc.impl.ClientProxies.getApplicationScopedDelegate(ClientProxies.java:19)
at io.quarkus.arc.generator.SlashCommandBuilderProducer_ProducerMethod_getSlashCommandBuilders_fe96c7e672b8b38361a2d9554b9c13bcb851b3a6_ClientProxy.arc$delegate(Unknown Source)
at io.quarkus.arc.generator.SlashCommandBuilderProducer_ProducerMethod_getSlashCommandBuilders_fe96c7e672b8b38361a2d9554b9c13bcb851b3a6_ClientProxy.size(Unknown Source)
at de.saladoc.quarkustest.JavacordRegistrar.onStartup(JavacordRegistrar.java:27)
at de.saladoc.quarkustest.JavacordRegistrar_Subclass.onStartup$$superforward1(Unknown Source)
at de.saladoc.quarkustest.JavacordRegistrar_Subclass$$function$$1.apply(Unknown Source)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:53)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.proceed(InvocationInterceptor.java:62)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.monitor(InvocationInterceptor.java:49)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.intercept(Unknown Source)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:40)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
at de.saladoc.quarkustest.JavacordRegistrar_Subclass.onStartup(Unknown Source)
at de.saladoc.quarkustest.JavacordRegistrar_Observer_onStartup_31ab13d40a0e2d112e6a2686ea6095750d382e87.notify(Unknown Source)
at io.quarkus.arc.impl.EventImpl$Notifier.notifyObservers(EventImpl.java:323)
at io.quarkus.arc.impl.EventImpl$Notifier.notify(EventImpl.java:305)
at io.quarkus.arc.impl.EventImpl.fire(EventImpl.java:73)
at io.quarkus.arc.runtime.ArcRecorder.fireLifecycleEvent(ArcRecorder.java:130)
at io.quarkus.arc.runtime.ArcRecorder.handleLifecycleEvents(ArcRecorder.java:99)
at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy_0(Unknown Source)
at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy(Unknown Source)
at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
at io.quarkus.runtime.Application.start(Application.java:101)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:103)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:67)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:41)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:120)
at io.quarkus.runner.GeneratedMain.main(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:103)
at java.base/java.lang.Thread.run(Thread.java:833)
Second issue: If the annotation command is disabled, the override-command is successfully registered. Executing it however fails, as the BotOwnerJavacordSlash
restriction can not be verified:
2022-06-28 22:01:35,028 ERROR [org.jav.cor.uti.eve.EventDispatcherBase] (Javacord - Central ExecutorService - 1) Unhandled exception in a listener thread for Saladocs Testserver!: java.lang.IllegalArgumentException: The restriction 'class net.kautler.command.api.restriction.javacord.slash.BotOwnerJavacordSlash' was not found in the given available restrictions '{class net.kautler.command.api.restriction.javacord.slash.PrivateMessageJavacordSlash_Subclass=net.kautler.command.api.restriction.javacord.slash.PrivateMessageJavacordSlash_Subclass@5bfa193b, class net.kautler.command.api.restriction.javacord.slash.NsfwChannelJavacordSlash_Subclass=net.kautler.command.api.restriction.javacord.slash.NsfwChannelJavacordSlash_Subclass@d4bc0aa, class net.kautler.command.api.restriction.javacord.slash.ServerOwnerJavacordSlash_Subclass=net.kautler.command.api.restriction.javacord.slash.ServerOwnerJavacordSlash_Subclass@c3d860e, class net.kautler.command.api.restriction.Everyone_Subclass=net.kautler.command.api.restriction.Everyone_Subclass@70fb4cc1, class net.kautler.command.api.restriction.javacord.slash.BotOwnerJavacordSlash_Subclass=net.kautler.command.api.restriction.javacord.slash.BotOwnerJavacordSlash_Subclass@7b43a024, class net.kautler.command.api.restriction.javacord.slash.ServerManagerJavacordSlash_Subclass=net.kautler.command.api.restriction.javacord.slash.ServerManagerJavacordSlash_Subclass@28de7176}'
at net.kautler.command.api.restriction.RestrictionChainElement.isCommandAllowed(RestrictionChainElement.java:66)
at net.kautler.command.api.CommandHandler.isCommandAllowed(CommandHandler.java:637)
at net.kautler.command.api.CommandHandler.executeCommand(CommandHandler.java:613)
at net.kautler.command.api.CommandHandler.computeCommand(CommandHandler.java:524)
at net.kautler.command.api.CommandHandler.fastForward(CommandHandler.java:574)
at net.kautler.command.api.CommandHandler.doHandleMessage(CommandHandler.java:275)
at net.kautler.command.handler.CommandHandlerJavacordSlash_Subclass.doHandleMessage$$superforward1(Unknown Source)
at net.kautler.command.handler.CommandHandlerJavacordSlash_Subclass$$function$$15.apply(Unknown Source)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:53)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.proceed(InvocationInterceptor.java:62)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.monitor(InvocationInterceptor.java:51)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.intercept(Unknown Source)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:40)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
at net.kautler.command.handler.CommandHandlerJavacordSlash_Subclass.doHandleMessage(Unknown Source)
at net.kautler.command.handler.CommandHandlerJavacordSlash.handleSlashCommandCreateEvent(CommandHandlerJavacordSlash.java:198)
at org.javacord.core.util.event.EventDispatcher.lambda$dispatchSlashCommandCreateEvent$101(EventDispatcher.java:3580)
at org.javacord.core.util.event.EventDispatcherBase.lambda$dispatchEvent$12(EventDispatcherBase.java:213)
at org.javacord.core.util.event.EventDispatcherBase.lambda$checkRunningListenersAndStartIfPossible$20(EventDispatcherBase.java:281)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
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.