Merge pull request #48 from Sauilitired/example-javacord

Add Example Javacord Implementation
This commit is contained in:
JarFiles 2020-10-14 13:15:37 +02:00 committed by GitHub
commit 7fd7c89882
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 599 additions and 0 deletions

View file

@ -0,0 +1,29 @@
apply plugin: "application"
apply plugin: "com.github.johnrengelman.shadow"
application {
mainClassName = "cloud.commandframework.examples.javacord.ExampleBot"
}
build.dependsOn(shadowJar)
repositories {
maven {
url = "https://repo.simplix.dev/repository/simplixsoft-public/"
}
}
dependencies {
/* Cloud */
implementation project(":cloud-javacord")
/* Utilities */
implementation "dev.simplix.core:simplixcore-common-api:1.0.0-20201013.161011-1"
implementation "dev.simplix.core:simplixcore-common-implementation:1.0.0-20201013.161028-1"
/* Javacord */
implementation "org.javacord:javacord:3.1.1"
/* Logger */
implementation "org.slf4j:slf4j-api:2.0.0-alpha1"
runtimeOnly "ch.qos.logback:logback-classic:1.3.0-alpha5"
runtimeOnly 'org.apache.logging.log4j:log4j-to-slf4j:2.11.0'
}

View file

@ -0,0 +1,61 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg & Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package cloud.commandframework.examples.javacord;
import dev.simplix.core.common.aop.ScanComponents;
import dev.simplix.core.common.aop.SimplixApplication;
import dev.simplix.core.common.inject.SimplixInstaller;
import dev.simplix.core.common.platform.Platform;
import org.checkerframework.checker.nullness.qual.NonNull;
import static cloud.commandframework.examples.javacord.ExampleBot.APPLICATION_NAME;
@SimplixApplication(
name = APPLICATION_NAME,
version = "1.0.0",
authors = "JarFiles"
)
@ScanComponents("cloud.commandframework.examples.javacord")
public final class ExampleBot {
public static final String APPLICATION_NAME = "ExampleBot";
private ExampleBot() {
throw new UnsupportedOperationException();
}
/**
* Starts the bot
*
* @param args Arguments to start the bot with (NOT used)
*/
public static void main(@NonNull final String[] args) {
SimplixInstaller
.instance()
.register(ExampleBot.class);
SimplixInstaller.instance().install(Platform.STANDALONE);
}
}

View file

@ -0,0 +1,123 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg & Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package cloud.commandframework.examples.javacord.application;
import cloud.commandframework.arguments.standard.IntegerArgument;
import cloud.commandframework.examples.javacord.components.CommandsComponent;
import cloud.commandframework.examples.javacord.components.DiscordApiComponent;
import cloud.commandframework.examples.javacord.modules.ExampleModule;
import cloud.commandframework.javacord.sender.JavacordPrivateSender;
import com.google.inject.Inject;
import dev.simplix.core.common.aop.AlwaysConstruct;
import dev.simplix.core.common.aop.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.javacord.api.entity.message.MessageAuthor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@Component(ExampleModule.class)
@AlwaysConstruct
public class ExampleApplication {
private final DiscordApiComponent discordApiComponent;
private final CommandsComponent commandsComponent;
private final ScheduledExecutorService executorService;
/**
* Starts a new ExampleBot. Done automatically
*
* @param discordApiComponent Instance of the {@link DiscordApiComponent} required for logging in to Discord
* @param commandsComponent Instance of the {@link CommandsComponent} used for registering commands
* @param executorService {@link java.util.concurrent.ScheduledThreadPoolExecutor} instance for scheduling tasks
* @throws Exception if something went wrong while starting the bot
*/
@Inject
public ExampleApplication(
@NonNull final DiscordApiComponent discordApiComponent,
@NonNull final CommandsComponent commandsComponent,
@NonNull final ScheduledExecutorService executorService
) throws
Exception {
this.discordApiComponent = discordApiComponent;
this.commandsComponent = commandsComponent;
this.executorService = executorService;
this.connectToDiscord();
this.registerCommands();
}
private void connectToDiscord() {
this.discordApiComponent.login(System.getProperty("bot.token"));
}
@SuppressWarnings("ConstantConditions")
private void registerCommands() throws Exception {
this.commandsComponent.initializeCommandManager();
this.commandsComponent.registerCommand(this.commandsComponent.getCommandManager()
.commandBuilder("ping")
.handler(context -> context.getSender().sendMessage("Pong!")).build());
this.commandsComponent.registerCommand(this.commandsComponent.getCommandManager()
.commandBuilder("shutdown", "sd")
.flag(this.commandsComponent.getCommandManager()
.flagBuilder("time")
.withAliases("t")
.withArgument(IntegerArgument.optional("time", 60)))
.senderType(JavacordPrivateSender.class)
.handler(context -> {
final MessageAuthor messageAuthor = context.getSender().getAuthor();
messageAuthor.asUser().ifPresent(user -> {
if (!user.getIdAsString().equals(System.getProperty("bot.owner"))) {
context.getSender().sendErrorMessage("You need to be the owner of the bot to do this!");
return;
}
final int time = context.flags().getValue("time", 60);
if (time > 0) {
context.getSender().sendSuccessMessage("Shutting down in " + time + " seconds!");
this.executorService.schedule(this::shutdown, time, TimeUnit.SECONDS);
return;
}
context.getSender().sendSuccessMessage("Shutting down now...");
this.shutdown();
});
})
.build());
}
/**
* Shuts off the bot completely. You should not do anything after executing this method!
*/
public void shutdown() {
this.executorService.shutdown();
this.discordApiComponent.shutdown();
System.exit(0);
}
}

View file

@ -0,0 +1,28 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg & Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
/**
* Javacord example application
*/
package cloud.commandframework.examples.javacord.application;

View file

@ -0,0 +1,104 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg & Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package cloud.commandframework.examples.javacord.components;
import cloud.commandframework.Command;
import cloud.commandframework.examples.javacord.modules.ExampleModule;
import cloud.commandframework.execution.CommandExecutionCoordinator;
import cloud.commandframework.javacord.JavacordCommandManager;
import cloud.commandframework.javacord.sender.JavacordCommandSender;
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import dev.simplix.core.common.aop.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.function.Function;
@Component(ExampleModule.class)
public class CommandsComponent {
private static final Logger LOG = LoggerFactory.getLogger(CommandsComponent.class);
private static final String COMMAND_PREFIX = "!";
private final DiscordApiComponent discordApiComponent;
private JavacordCommandManager<@NonNull JavacordCommandSender> commandManager;
/**
* Creates a new instance of the CommandsComponent used for registering commands. Done automatically
*
* @param discordApiComponent Instance of the {@link DiscordApiComponent} for registering the command listener
*/
@Inject
public CommandsComponent(@NonNull final DiscordApiComponent discordApiComponent) {
this.discordApiComponent = discordApiComponent;
}
/**
* Creates a new {@link JavacordCommandManager} instance
*
* @throws Exception If something went wrong while instantiating the CommandManager
*/
public final void initializeCommandManager() throws Exception {
Preconditions.checkArgument(
this.commandManager == null,
"The CommandManager instance has already been created!"
);
LOG.info("Instantiating new Command Manager");
this.commandManager = new JavacordCommandManager<>(
this.discordApiComponent.getDiscordApi(),
CommandExecutionCoordinator.simpleCoordinator(),
Function.identity(),
Function.identity(),
sender -> COMMAND_PREFIX,
null
);
}
/**
* Registers a new {@link Command}
*
* @param command Command which should be registered
*/
public final void registerCommand(final @NonNull Command<@NonNull JavacordCommandSender> command) {
LOG.info("Registering Command: " + command.getArguments().get(0).getName());
this.getCommandManager().command(command);
}
/**
* Gets the {@link JavacordCommandManager} instance
*
* @return The CommandManager
*/
public final @NonNull JavacordCommandManager<@NonNull JavacordCommandSender> getCommandManager() {
Preconditions.checkNotNull(this.commandManager, "Command Manager has not been initialized yet");
return this.commandManager;
}
}

View file

@ -0,0 +1,103 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg & Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package cloud.commandframework.examples.javacord.components;
import cloud.commandframework.examples.javacord.modules.ExampleModule;
import com.google.common.base.Preconditions;
import dev.simplix.core.common.aop.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.javacord.api.DiscordApi;
import org.javacord.api.DiscordApiBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(ExampleModule.class)
public class DiscordApiComponent {
private static final Logger LOG = LoggerFactory.getLogger(DiscordApiComponent.class);
private final DiscordApiBuilder builder;
private DiscordState discordState;
private DiscordApi api;
/**
* Creates a new {@link DiscordApiComponent} instance. Done automatically
*/
public DiscordApiComponent() {
this.builder = new DiscordApiBuilder();
this.discordState = DiscordState.DISCONNECTED;
}
/**
* Logs in to Discord using the provided token
*
* @param token The Discord Bot token
*/
public final void login(@NonNull final String token) {
LOG.info("Logging in to Discord...");
this.api = this.builder.setToken(token).login().join();
this.discordState = DiscordState.CONNECTED;
LOG.info("Successfully connected to Discord!");
}
/**
* Shuts of the {@link DiscordApi} instance
*/
public final void shutdown() {
LOG.info("Shutting down DiscordApi instance...");
this.api.disconnect();
this.discordState = DiscordState.DISCONNECTED;
LOG.info("Successfully shut of the DiscordApi");
}
/**
* Gets the current {@link DiscordApi} instance
*
* @return Instance of the DiscordApi
*/
public final @NonNull DiscordApi getDiscordApi() {
Preconditions.checkArgument(this.discordState == DiscordState.CONNECTED, "Not connected to Discord");
return this.api;
}
/**
* Gets the current Api State
*
* @return Current Api State
*/
public final @NonNull DiscordState getDiscordState() {
return this.discordState;
}
public enum DiscordState {
CONNECTED,
DISCONNECTED
}
}

View file

@ -0,0 +1,28 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg & Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
/**
* Javacord example components
*/
package cloud.commandframework.examples.javacord.components;

View file

@ -0,0 +1,51 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg & Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package cloud.commandframework.examples.javacord.modules;
import com.google.inject.Inject;
import com.google.inject.Provides;
import dev.simplix.core.common.aop.AbstractSimplixModule;
import dev.simplix.core.common.aop.ApplicationModule;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import static cloud.commandframework.examples.javacord.ExampleBot.APPLICATION_NAME;
@ApplicationModule(APPLICATION_NAME)
public class ExampleModule extends AbstractSimplixModule {
/**
* Creates a new {@link ScheduledExecutorService} instance. Done automatically
*
* @return Instance of the ExecutorService
*/
@Provides
@Inject
public final @NonNull ScheduledExecutorService provideExecutorService() {
return Executors.newScheduledThreadPool(0);
}
}

View file

@ -0,0 +1,28 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg & Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
/**
* Javacord example modules
*/
package cloud.commandframework.examples.javacord.modules;

View file

@ -0,0 +1,28 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg & Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
/**
* Javacord example bot
*/
package cloud.commandframework.examples.javacord;

View file

@ -0,0 +1,14 @@
<configuration>
<appender class="ch.qos.logback.core.ConsoleAppender" name="console">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %msg%n</pattern>
</encoder>
<target>System.out</target>
</appender>
<root level="info">
<appender-ref ref="console"/>
</root>
</configuration>

View file

@ -12,6 +12,7 @@ include(':cloud-cloudburst')
include(':cloud-javacord')
include(':cloud-jda')
include(':example-bukkit')
include(':example-javacord')
include(':cloud-tasks')
include(':cloud-sponge')
project(':cloud-bukkit').projectDir = file('cloud-minecraft/cloud-bukkit')
@ -24,4 +25,5 @@ project(':cloud-cloudburst').projectDir = file('cloud-minecraft/cloud-cloudburst
project(':cloud-javacord').projectDir = file('cloud-discord/cloud-javacord')
project(':cloud-jda').projectDir = file('cloud-discord/cloud-jda')
project(':example-bukkit').projectDir = file('examples/example-bukkit')
project(':example-javacord').projectDir = file('examples/example-javacord')
project(':cloud-sponge').projectDir = file('cloud-minecraft/cloud-sponge')