-
-
Notifications
You must be signed in to change notification settings - Fork 266
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update bot example files and command rework
- Loading branch information
Showing
14 changed files
with
731 additions
and
512 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* This file is part of Discord4J. | ||
* | ||
* Discord4J is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* Discord4J is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with Discord4J. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package discord4j.core.command; | ||
|
||
import org.reactivestreams.Publisher; | ||
|
||
import java.util.function.BiFunction; | ||
|
||
public interface Command extends BiFunction<CommandRequest, CommandResponse, Publisher<Void>> { | ||
} |
48 changes: 48 additions & 0 deletions
48
core/src/test/java/discord4j/core/command/CommandHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* This file is part of Discord4J. | ||
* | ||
* Discord4J is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* Discord4J is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with Discord4J. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package discord4j.core.command; | ||
|
||
import org.reactivestreams.Publisher; | ||
|
||
import java.util.Objects; | ||
import java.util.function.BiFunction; | ||
import java.util.function.Predicate; | ||
|
||
class CommandHandler implements BiFunction<CommandRequest, CommandResponse, Publisher<Void>>, | ||
Predicate<CommandRequest> { | ||
|
||
final Predicate<? super CommandRequest> condition; | ||
final BiFunction<? super CommandRequest, ? super CommandResponse, ? extends Publisher<Void>> handler; | ||
|
||
public CommandHandler( | ||
Predicate<? super CommandRequest> condition, | ||
BiFunction<? super CommandRequest, ? super CommandResponse, ? extends Publisher<Void>> handler) { | ||
this.condition = Objects.requireNonNull(condition, "condition"); | ||
this.handler = Objects.requireNonNull(handler, "handler"); | ||
} | ||
|
||
@Override | ||
public Publisher<Void> apply(CommandRequest request, CommandResponse response) { | ||
return handler.apply(request, response); | ||
} | ||
|
||
@Override | ||
public boolean test(CommandRequest request) { | ||
return condition.test(request); | ||
} | ||
} |
110 changes: 110 additions & 0 deletions
110
core/src/test/java/discord4j/core/command/CommandListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* | ||
* This file is part of Discord4J. | ||
* | ||
* Discord4J is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* Discord4J is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with Discord4J. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package discord4j.core.command; | ||
|
||
import discord4j.common.annotations.Experimental; | ||
import discord4j.core.event.ReactiveEventAdapter; | ||
import discord4j.core.event.domain.message.MessageCreateEvent; | ||
import discord4j.core.object.entity.User; | ||
import org.reactivestreams.Publisher; | ||
import reactor.core.publisher.Flux; | ||
import reactor.core.publisher.Mono; | ||
import reactor.util.function.Tuples; | ||
|
||
import java.util.Objects; | ||
import java.util.concurrent.CopyOnWriteArrayList; | ||
import java.util.function.Function; | ||
import java.util.function.Predicate; | ||
|
||
@Experimental | ||
public class CommandListener extends ReactiveEventAdapter { | ||
|
||
private final Function<MessageCreateEvent, Publisher<String>> prefixFunction; | ||
private final Function<? super CommandRequest, Mono<Boolean>> filter; | ||
private final CopyOnWriteArrayList<CommandHandler> handlers = new CopyOnWriteArrayList<>(); | ||
|
||
CommandListener(Function<MessageCreateEvent, Publisher<String>> prefixFunction, | ||
Function<? super CommandRequest, Mono<Boolean>> filter) { | ||
this.prefixFunction = prefixFunction; | ||
this.filter = filter; | ||
} | ||
|
||
CommandListener(CommandListener source) { | ||
this.prefixFunction = source.prefixFunction; | ||
this.filter = source.filter; | ||
} | ||
|
||
public static CommandListener create() { | ||
return createWithPrefix(__ -> Mono.just("")); | ||
} | ||
|
||
public static CommandListener createWithPrefix(String prefix) { | ||
return createWithPrefix(__ -> Mono.justOrEmpty(prefix)); | ||
} | ||
|
||
public static CommandListener createWithPrefix(Function<MessageCreateEvent, Publisher<String>> prefixFunction) { | ||
return new CommandListener(Objects.requireNonNull(prefixFunction, "prefixFunction"), __ -> Mono.just(true)); | ||
} | ||
|
||
public CommandListener filter(Function<? super CommandRequest, Mono<Boolean>> condition) { | ||
return new CommandListener(this.prefixFunction, | ||
req -> this.filter.apply(req).flatMap(result -> condition.apply(req))); | ||
} | ||
|
||
public CommandListener on(String command, Command handler) { | ||
return handle(request -> request.command().equals(command), handler); | ||
} | ||
|
||
public CommandListener handle(Predicate<? super CommandRequest> condition, Command handler) { | ||
handlers.add(new CommandHandler(condition, handler)); | ||
return this; | ||
} | ||
|
||
public CommandListener handle(Command handler) { | ||
handlers.add(new CommandHandler(__ -> true, handler)); | ||
return this; | ||
} | ||
|
||
@Override | ||
public Publisher<?> onMessageCreate(MessageCreateEvent event) { | ||
if (event.getMessage().getAuthor().map(User::isBot).orElse(true)) { | ||
return Mono.empty(); | ||
} else { | ||
String content = event.getMessage().getContent(); | ||
return Flux.defer(() -> prefixFunction.apply(event)) | ||
.filter(content::startsWith) | ||
.map(prefix -> { | ||
String trimmed = content.substring(prefix.length()).trim(); | ||
int endIndex = (trimmed.indexOf(' ') < 0) ? trimmed.length() : trimmed.indexOf(' '); | ||
String commandName = trimmed.substring(0, endIndex); | ||
String remaining = trimmed.substring(commandName.length()).trim(); | ||
return Tuples.of( | ||
new DefaultCommandRequest(event, commandName, remaining), | ||
new DefaultCommandResponse(event) | ||
); | ||
}) | ||
.filterWhen(exchange -> filter.apply(exchange.getT1())) | ||
.flatMap(exchange -> handlers.stream() | ||
.filter(handler -> handler.test(exchange.getT1())) | ||
.map(handler -> handler.apply(exchange.getT1(), exchange.getT2())) | ||
.findFirst() | ||
.orElse(Mono.empty())); | ||
// TODO: use CommandResponse to manage event lifecycle | ||
} | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
core/src/test/java/discord4j/core/command/CommandRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* This file is part of Discord4J. | ||
* | ||
* Discord4J is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* Discord4J is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with Discord4J. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package discord4j.core.command; | ||
|
||
import discord4j.core.GatewayDiscordClient; | ||
import discord4j.core.event.domain.message.MessageCreateEvent; | ||
import discord4j.core.object.entity.Message; | ||
import discord4j.core.object.entity.User; | ||
import discord4j.core.object.entity.channel.GuildChannel; | ||
import discord4j.rest.util.PermissionSet; | ||
import reactor.core.publisher.Mono; | ||
|
||
import java.util.Optional; | ||
|
||
public interface CommandRequest { | ||
|
||
MessageCreateEvent event(); | ||
|
||
String command(); | ||
|
||
String parameters(); | ||
|
||
default GatewayDiscordClient getClient() { | ||
return event().getClient(); | ||
} | ||
|
||
default Message getMessage() { | ||
return event().getMessage(); | ||
} | ||
|
||
default Optional<User> getAuthor() { | ||
return event().getMessage().getAuthor(); | ||
} | ||
|
||
default Mono<Boolean> hasPermission(PermissionSet requiredPermissions) { | ||
return Mono.justOrEmpty(getAuthor().map(User::getId)) | ||
.flatMap(authorId -> getMessage().getChannel().ofType(GuildChannel.class) | ||
.flatMap(channel -> channel.getEffectivePermissions(authorId)) | ||
.map(set -> set.containsAll(requiredPermissions))); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
core/src/test/java/discord4j/core/command/CommandResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* This file is part of Discord4J. | ||
* | ||
* Discord4J is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* Discord4J is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with Discord4J. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package discord4j.core.command; | ||
|
||
import discord4j.core.GatewayDiscordClient; | ||
import discord4j.core.object.entity.channel.MessageChannel; | ||
import discord4j.core.object.entity.channel.PrivateChannel; | ||
import reactor.core.publisher.Mono; | ||
|
||
public interface CommandResponse { | ||
|
||
GatewayDiscordClient getClient(); | ||
|
||
Mono<MessageChannel> getReplyChannel(); | ||
|
||
Mono<PrivateChannel> getPrivateChannel(); | ||
|
||
// TODO: add error(...) methods for common error handling | ||
} |
Oops, something went wrong.