Add JDA example

Basic example also showing a basic implementation of the permission mapper
This commit is contained in:
broccolai 2020-10-20 08:50:32 +01:00 committed by Alexander Söderberg
parent c0bc1e7523
commit 0715c4ab9d
8 changed files with 458 additions and 0 deletions

View file

@ -0,0 +1,18 @@
apply plugin: "application"
apply plugin: "com.github.johnrengelman.shadow"
application {
mainClassName = "cloud.commandframework.examples.jda.ExampleBot"
}
repositories {
jcenter()
}
dependencies {
implementation project(":cloud-jda")
implementation 'net.dv8tion:JDA:4.2.0_207'
implementation 'org.slf4j:slf4j-simple:1.7.21'
}
build.dependsOn(shadowJar)

View file

@ -0,0 +1,64 @@
//
// 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.jda;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.User;
import org.checkerframework.checker.nullness.qual.NonNull;
public abstract class CustomUser {
private final User user;
private final MessageChannel channel;
/**
* Construct a user
*
* @param user Sending user
* @param channel Channel that the message was sent in
*/
public CustomUser(final @NonNull User user, final @NonNull MessageChannel channel) {
this.user = user;
this.channel = channel;
}
/**
* Get the user that sent the message
*
* @return Sending user
*/
public final @NonNull User getUser() {
return user;
}
/**
* Get the channel the message was sent in
*
* @return Message channel
*/
public final @NonNull MessageChannel getChannel() {
return channel;
}
}

View file

@ -0,0 +1,149 @@
//
// 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.jda;
import cloud.commandframework.Command;
import cloud.commandframework.arguments.standard.StringArgument;
import cloud.commandframework.execution.CommandExecutionCoordinator;
import cloud.commandframework.jda.JDACommandManager;
import cloud.commandframework.jda.JDAGuildSender;
import cloud.commandframework.jda.JDAPrivateSender;
import cloud.commandframework.jda.parsers.UserArgument;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.utils.ChunkingFilter;
import net.dv8tion.jda.api.utils.MemberCachePolicy;
import org.checkerframework.checker.nullness.qual.NonNull;
import javax.security.auth.login.LoginException;
public final class ExampleBot {
private ExampleBot() {
throw new UnsupportedOperationException();
}
/**
* Starts the bot
*
* @param args Arguments to start the bot
* @throws InterruptedException When the jda instance does not ready correctly
* @throws LoginException If the bots token isn't correct
*/
public static void main(final @NonNull String[] args) throws InterruptedException, LoginException {
final JDA jda = JDABuilder.createDefault(System.getProperty("token"))
.setAutoReconnect(true)
.setChunkingFilter(ChunkingFilter.ALL)
.setMemberCachePolicy(MemberCachePolicy.ALL)
.enableIntents(GatewayIntent.GUILD_MEMBERS)
.setActivity(Activity.playing("GAMES"))
.build();
final PermissionRegistry permissionRegistry = new PermissionRegistry();
final JDACommandManager<CustomUser> commandManager = new JDACommandManager<>(
jda,
message -> "!",
(sender, permission) -> permissionRegistry.hasPermission(sender.getUser().getIdLong(), permission),
CommandExecutionCoordinator.simpleCoordinator(),
sender -> {
if (sender instanceof JDAPrivateSender) {
JDAPrivateSender jdaPrivateSender = (JDAPrivateSender) sender;
return new PrivateUser(jdaPrivateSender.getUser(), jdaPrivateSender.getPrivateChannel());
}
if (sender instanceof JDAGuildSender) {
JDAGuildSender jdaGuildSender = (JDAGuildSender) sender;
return new GuildUser(jdaGuildSender.getMember(), jdaGuildSender.getTextChannel());
}
throw new UnsupportedOperationException();
},
user -> {
if (user instanceof PrivateUser) {
PrivateUser privateUser = (PrivateUser) user;
return new JDAPrivateSender(null, privateUser.getUser(), privateUser.getPrivateChannel());
}
if (user instanceof GuildUser) {
GuildUser guildUser = (GuildUser) user;
return new JDAGuildSender(null, guildUser.getMember(), guildUser.getTextChannel());
}
throw new UnsupportedOperationException();
}
);
commandManager.command(commandManager
.commandBuilder("ping")
.handler(context -> {
context.getSender().getChannel().sendMessage("pong").complete();
}));
final Command.Builder<CustomUser> builder = commandManager.commandBuilder("permission");
commandManager.command(builder
.literal("add")
.argument(UserArgument.of("user"))
.argument(StringArgument.single("perm"))
.handler(context -> {
final User user = context.get("user");
final String perm = context.get("perm");
permissionRegistry.add(user.getIdLong(), perm);
context.getSender().getChannel().sendMessage("permission added").complete();
}));
commandManager.command(builder
.literal("remove")
.argument(UserArgument.of("user"))
.argument(StringArgument.single("perm"))
.handler(context -> {
final User user = context.get("user");
final String perm = context.get("perm");
permissionRegistry.remove(user.getIdLong(), perm);
context.getSender().getChannel().sendMessage("permission removed").complete();
}));
commandManager.command(commandManager
.commandBuilder("kick")
.senderType(GuildUser.class)
.permission("kick")
.argument(UserArgument.of("user"))
.handler(context -> {
final GuildUser guildUser = (GuildUser) context.getSender();
final TextChannel textChannel = guildUser.getTextChannel();
final User user = context.get("user");
textChannel.getGuild().kick(user.getId()).complete();
textChannel.sendMessage(user.getName() + " kicked").complete();
}));
}
}

View file

@ -0,0 +1,65 @@
//
// 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.jda;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.TextChannel;
import org.checkerframework.checker.nullness.qual.NonNull;
public final class GuildUser extends CustomUser {
private final Member member;
private final TextChannel channel;
/**
* Construct a Guild user
*
* @param member Guild member that sent the message
* @param channel Text channel that the message was sent in
*/
public GuildUser(final @NonNull Member member, final @NonNull TextChannel channel) {
super(member.getUser(), channel);
this.member = member;
this.channel = channel;
}
/**
* Get the member that sent the message
*
* @return Sending member
*/
public @NonNull Member getMember() {
return member;
}
/**
* Get the text channel the message was sent in
*
* @return Message channel
*/
public @NonNull TextChannel getTextChannel() {
return channel;
}
}

View file

@ -0,0 +1,78 @@
//
// 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.jda;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public final class PermissionRegistry {
private final Map<Long, Set<String>> permissions = new HashMap<>();
/**
* Add a permission to a user
*
* @param userId Users id
* @param permission Permission to add
*/
public void add(final @NonNull Long userId, final @NonNull String permission) {
this.getPermissions(userId).add(permission.toLowerCase());
}
/**
* Remove a permission from a user
*
* @param userId Users id
* @param permission Permission to remove
*/
public void remove(final @NonNull Long userId, final @NonNull String permission) {
this.getPermissions(userId).remove(permission.toLowerCase());
}
/**
* Check if a user has a specific permission
*
* @param userId Users id
* @param permission Permission to check
* @return True if the user has a permission
*/
public boolean hasPermission(final @NonNull Long userId, final @Nullable String permission) {
if (permission == null) {
return true;
}
return this.getPermissions(userId).contains(permission.toLowerCase());
}
private Set<String> getPermissions(final @NonNull Long userId) {
this.permissions.putIfAbsent(userId, new HashSet<>());
return this.permissions.get(userId);
}
}

View file

@ -0,0 +1,54 @@
//
// 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.jda;
import net.dv8tion.jda.api.entities.PrivateChannel;
import net.dv8tion.jda.api.entities.User;
import org.checkerframework.checker.nullness.qual.NonNull;
public final class PrivateUser extends CustomUser {
private final PrivateChannel privateChannel;
/**
* Construct a Private user
*
* @param user User that sent the message
* @param channel Text channel that the message was sent in
*/
public PrivateUser(final @NonNull User user, final @NonNull PrivateChannel channel) {
super(user, channel);
this.privateChannel = channel;
}
/**
* Get the private channel the message was sent in
*
* @return Private channel
*/
public @NonNull PrivateChannel getPrivateChannel() {
return privateChannel;
}
}

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.
//
/**
* JDA example bot
*/
package cloud.commandframework.examples.jda;

View file

@ -13,6 +13,7 @@ include(':cloud-javacord')
include(':cloud-jda')
include(':example-bukkit')
include(':example-javacord')
include(':example-jda')
include(':cloud-tasks')
include(':cloud-sponge')
include(':example-velocity')
@ -28,6 +29,7 @@ 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(':example-jda').projectDir = file('examples/example-jda')
project(':cloud-sponge').projectDir = file('cloud-minecraft/cloud-sponge')
project(':example-velocity').projectDir = file('examples/example-velocity')
project(':example-bungee').projectDir = file('examples/example-bungee')