GithubHelp home page GithubHelp logo

vampire / command-framework Goto Github PK

View Code? Open in Web Editor NEW
13.0 13.0 5.0 986 KB

A generic CDI-based command framework

License: Apache License 2.0

Kotlin 4.61% ANTLR 0.12% Java 27.66% Groovy 67.62%

command-framework's People

Contributors

bastian avatar vampire avatar walkerknapp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

command-framework's Issues

Allow restricting commands to arbitrary permission

What?

Allow restriction of a command to an arbitrary permission understood by discord (or rather javacord/jda) without having to create a custom Restriction implementation.

Why?

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:

  • Restricting a cleanup command to users with the MANAGE_MESSAGES permission.
  • Restricting a mass timeout/kick/ban command to users with the MODERATE_MEMBERS/KICK_MEMBERS/BAN_MEMBERS permission

Providing 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.

What it...

should be

  • Provide a class or interface for parameter based restrictions.
  • Allow to specify whether the ADMINISTRATOR permission being present should also be accepted (defaults to true)
  • Provide an annotation like RestrictedToPermission("MANAGE_MESSAGES") or RestrictedToPermission("MANAGE_MESSAGES", acceptAdmin=false)

might be

  • Implementation-specific with different annotations / classes / interfaces for Javacord and JDA accepting their respective permission types
  • Extensible for custom string-based permission systems (provided a resolver is supplied)

should not be

  • anything more than that

Problems / Thoughts

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.

Issues using the framework with quarkus

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.