Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c45221ae9a | ||
|
|
f4b5ad30b3 | ||
|
|
a4345d30da | ||
|
|
d0de70ab3f | ||
|
|
fdf262969a | ||
|
|
fb2835f427 | ||
|
|
54a27883d1 | ||
|
|
196f0be044 | ||
|
|
571713a9ec | ||
|
|
703f503191 |
No files matched your search
+58
-50
@@ -10,10 +10,15 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- "main"
|
- "main"
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
package:
|
package:
|
||||||
name: Package
|
name: Package
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
|
timeout-minutes: 15
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||||
@@ -32,7 +37,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload test reports
|
- name: Upload test reports
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@c6a366c94c3e0affe28c06c8df20a878f24da3cf # v3
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||||
with:
|
with:
|
||||||
name: junit-reports
|
name: junit-reports
|
||||||
path: |
|
path: |
|
||||||
@@ -40,7 +45,7 @@ jobs:
|
|||||||
if-no-files-found: ignore
|
if-no-files-found: ignore
|
||||||
|
|
||||||
- name: Upload Maven artifacts
|
- name: Upload Maven artifacts
|
||||||
uses: actions/upload-artifact@c6a366c94c3e0affe28c06c8df20a878f24da3cf # v3
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||||
with:
|
with:
|
||||||
name: maven-artifacts
|
name: maven-artifacts
|
||||||
path: |
|
path: |
|
||||||
@@ -48,11 +53,40 @@ jobs:
|
|||||||
startup.sh
|
startup.sh
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
docker-main:
|
maven-publish:
|
||||||
name: Docker Build and Push (main)
|
name: Publish Maven Package
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
|
timeout-minutes: 15
|
||||||
needs: package
|
needs: package
|
||||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')) }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||||
|
|
||||||
|
- name: Set up JDK
|
||||||
|
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '25'
|
||||||
|
cache: 'maven'
|
||||||
|
server-id: gitea
|
||||||
|
server-username: REGISTRY_USER
|
||||||
|
server-password: REGISTRY_PASSWORD
|
||||||
|
|
||||||
|
- name: Publish Maven package
|
||||||
|
run: |
|
||||||
|
chmod +x ./mvnw
|
||||||
|
./mvnw --batch-mode deploy -DskipTests
|
||||||
|
env:
|
||||||
|
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
|
||||||
|
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
|
docker:
|
||||||
|
name: Docker Build and Push
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
timeout-minutes: 15
|
||||||
|
needs: package
|
||||||
|
if: ${{ github.event_name == 'push' }}
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
@@ -61,51 +95,25 @@ jobs:
|
|||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||||
|
|
||||||
- name: Download build artifacts
|
- name: Download build artifacts
|
||||||
uses: actions/download-artifact@a9bc5e6ef2cb54c177f32aa5726adaa15e7e2d59 # v3
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||||
with:
|
with:
|
||||||
name: maven-artifacts
|
name: maven-artifacts
|
||||||
path: .
|
path: .
|
||||||
|
|
||||||
- name: Log in to registry
|
- name: Compute Docker tags
|
||||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
|
id: meta
|
||||||
with:
|
|
||||||
registry: ${{ secrets.REGISTRY_URL }}
|
|
||||||
username: ${{ secrets.REGISTRY_USER }}
|
|
||||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Build and push (main)
|
|
||||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./Dockerfile
|
|
||||||
push: true
|
|
||||||
tags: "${{ secrets.REGISTRY_URL }}/${{ secrets.REGISTRY_USER }}/netneutrality:main"
|
|
||||||
|
|
||||||
docker-release:
|
|
||||||
name: Docker Build and Push (release)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: package
|
|
||||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
||||||
|
|
||||||
- name: Download build artifacts
|
|
||||||
uses: actions/download-artifact@a9bc5e6ef2cb54c177f32aa5726adaa15e7e2d59 # v3
|
|
||||||
with:
|
|
||||||
name: maven-artifacts
|
|
||||||
path: .
|
|
||||||
|
|
||||||
- name: Compute release version
|
|
||||||
id: rel
|
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
# Strip leading 'v' if present (e.g., v1.2.3 -> 1.2.3)
|
REGISTRY="${{ secrets.REGISTRY_URL }}/${{ secrets.REGISTRY_USER }}/netneutrality"
|
||||||
ver="${GITHUB_REF_NAME#v}"
|
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
|
||||||
echo "version=$ver" >> "$GITHUB_OUTPUT"
|
ver="${GITHUB_REF_NAME#v}"
|
||||||
|
echo "tags=${REGISTRY}:${ver},${REGISTRY}:latest" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "tags=${REGISTRY}:main" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v4
|
||||||
|
|
||||||
- name: Log in to registry
|
- name: Log in to registry
|
||||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
|
||||||
@@ -114,12 +122,12 @@ jobs:
|
|||||||
username: ${{ secrets.REGISTRY_USER }}
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
- name: Build and push (release + latest)
|
- name: Build and push
|
||||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7
|
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
${{ secrets.REGISTRY_URL }}/${{ secrets.REGISTRY_USER }}/netneutrality:${{ steps.rel.outputs.version }}
|
cache-from: type=registry,ref=${{ secrets.REGISTRY_URL }}/${{ secrets.REGISTRY_USER }}/netneutrality:buildcache
|
||||||
${{ secrets.REGISTRY_URL }}/${{ secrets.REGISTRY_USER }}/netneutrality:latest
|
cache-to: type=registry,ref=${{ secrets.REGISTRY_URL }}/${{ secrets.REGISTRY_USER }}/netneutrality:buildcache,mode=max
|
||||||
+1
-1
@@ -32,7 +32,7 @@ services:
|
|||||||
MYSQL_PASSWORD: password
|
MYSQL_PASSWORD: password
|
||||||
MYSQL_DATABASE: netneutrality
|
MYSQL_DATABASE: netneutrality
|
||||||
ejs-api:
|
ejs-api:
|
||||||
image: ghcr.io/kikkia/yt-cipher:master@sha256:4fbb0d94cb4b9d2e5028986853825921d8c30975c0d948391fb9f4c7bf8520f6
|
image: ghcr.io/kikkia/yt-cipher:master@sha256:4c5ec381ff57336cfc24822d2b526a5ad7cd0171f61065a1bbc87bb736842449
|
||||||
container_name: ejs_signature_api
|
container_name: ejs_signature_api
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -11,6 +11,13 @@
|
|||||||
<description>Discord bot</description>
|
<description>Discord bot</description>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>gitea</id>
|
||||||
|
<url>https://gitea.bobert.me/api/packages/anthorob/maven</url>
|
||||||
|
</repository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<main.class>me.bobert.netneutrality.NetNeutrality</main.class>
|
<main.class>me.bobert.netneutrality.NetNeutrality</main.class>
|
||||||
<java.version>25</java.version>
|
<java.version>25</java.version>
|
||||||
@@ -136,7 +143,7 @@
|
|||||||
<repository>
|
<repository>
|
||||||
<id>arbjergDev-releases</id>
|
<id>arbjergDev-releases</id>
|
||||||
<name>Lavalink Repository</name>
|
<name>Lavalink Repository</name>
|
||||||
<url>https://maven.lavalink.dev/releases</url>
|
<url>https://maven.lavalink.dev/snapshots</url>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
@@ -149,12 +156,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>dev.arbjerg</groupId>
|
<groupId>dev.arbjerg</groupId>
|
||||||
<artifactId>lavaplayer</artifactId>
|
<artifactId>lavaplayer</artifactId>
|
||||||
<version>2.2.6</version>
|
<version>2.2.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>dev.lavalink.youtube</groupId>
|
<groupId>dev.lavalink.youtube</groupId>
|
||||||
<artifactId>v2</artifactId>
|
<artifactId>v2</artifactId>
|
||||||
<version>1.18.1</version>
|
<version>f45bbb7aebfcbc1c553769e04af6cd43afa8b7c3-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>club.minnced</groupId>
|
<groupId>club.minnced</groupId>
|
||||||
@@ -226,11 +233,6 @@
|
|||||||
<artifactId>jemoji</artifactId>
|
<artifactId>jemoji</artifactId>
|
||||||
<version>1.7.6</version>
|
<version>1.7.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>net.fellbaum</groupId>
|
|
||||||
<artifactId>jemoji</artifactId>
|
|
||||||
<version>1.7.0</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.json</groupId>
|
<groupId>org.json</groupId>
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class NetNeutrality {
|
|||||||
options.setEnvironment(env);
|
options.setEnvironment(env);
|
||||||
options.setTracesSampleRate(1.0);
|
options.setTracesSampleRate(1.0);
|
||||||
options.setDebug(false);
|
options.setDebug(false);
|
||||||
options.setRelease(Settings.getVersion());
|
options.setRelease(VERSION);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,11 +37,6 @@ public class MusicChannelContext extends AbstractContext implements NoMessageCon
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFromGuild() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteMessage() {
|
public void deleteMessage() {
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.command;
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
public abstract class AbstractAdminCommand extends AbstractCommand {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean needAdmin() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandCategory getCategory() {
|
|
||||||
return CommandCategory.ADMINISTRATION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.command;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import me.bobert.netneutrality.context.command.MessageMenuContext;
|
|
||||||
import me.bobert.netneutrality.core.command.options.CommandOptionsBuilder;
|
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
|
||||||
|
|
||||||
public abstract class AbstractMessageMenuCommand extends AbstractCommand {
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isGuildOnly() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSlashCommandOnly() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
|
||||||
// no options for context commands
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandCategory getCategory() {
|
|
||||||
return CommandCategory.UNLISTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return Type.MESSAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandExecutionResult execute(CommandContext context) {
|
|
||||||
if (context instanceof MessageMenuContext mc) {
|
|
||||||
Message message = mc.getTarget();
|
|
||||||
return execute(message, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Wrong context type for this command");
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract CommandExecutionResult execute(Message target, CommandContext context);
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.command;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import me.bobert.netneutrality.context.command.UserMenuContext;
|
|
||||||
import me.bobert.netneutrality.core.command.options.CommandOptionsBuilder;
|
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
|
||||||
import net.dv8tion.jda.api.entities.User;
|
|
||||||
|
|
||||||
public abstract class AbstractUserMenuCommand extends AbstractCommand {
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSlashCommandOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
|
||||||
// no options for context commands
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return Type.USER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandExecutionResult execute(CommandContext context) {
|
|
||||||
if (context instanceof UserMenuContext uc) {
|
|
||||||
User user = uc.getTarget();
|
|
||||||
return execute(user, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Wrong context type for this command");
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract CommandExecutionResult execute(User target, CommandContext context);
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
<<<<<<<< HEAD:src/main/java/me/bobert/netneutrality/core/command/impl/AbstractCommand.java
|
|
||||||
package me.bobert.netneutrality.core.command.impl;
|
package me.bobert.netneutrality.core.command.impl;
|
||||||
========
|
|
||||||
package me.bobert.netneutrality.core.command;
|
|
||||||
>>>>>>>> 8479f71 (change package of core command classes so it makes more sense and rename getType() to getCategory() in command interface):src/main/java/me/bobert/netneutrality/core/command/AbstractCommand.java
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) anthorob
|
* Copyright (c) anthorob
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
<<<<<<<< HEAD:src/main/java/me/bobert/netneutrality/core/command/impl/MusicCommand.java
|
|
||||||
package me.bobert.netneutrality.core.command.impl;
|
package me.bobert.netneutrality.core.command.impl;
|
||||||
========
|
|
||||||
package me.bobert.netneutrality.core.command;
|
|
||||||
>>>>>>>> 8479f71 (change package of core command classes so it makes more sense and rename getType() to getCategory() in command interface):src/main/java/me/bobert/netneutrality/core/command/AbstractMusicCommand.java
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) anthorob
|
* Copyright (c) anthorob
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,170 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.command.options;
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.command.Command;
|
|
||||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
|
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData;
|
|
||||||
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.StringJoiner;
|
|
||||||
|
|
||||||
public class CommandOptions {
|
|
||||||
private final Command command;
|
|
||||||
private final CommandDataImpl commandData;
|
|
||||||
private final List<OptionData> options;
|
|
||||||
private final List<SubcommandData> subcommands;
|
|
||||||
private final List<SubcommandGroupData> subcommandGroups;
|
|
||||||
|
|
||||||
public CommandOptions(Command command, CommandDataImpl commandData) {
|
|
||||||
this.command = command;
|
|
||||||
this.commandData = commandData;
|
|
||||||
this.options = commandData.getOptions();
|
|
||||||
this.subcommands = commandData.getSubcommands();
|
|
||||||
this.subcommandGroups = commandData.getSubcommandGroups();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Command getCommand() {
|
|
||||||
return command;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SlashCommandData getSlashCommandData() {
|
|
||||||
return commandData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<OptionData> getOptions() {
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<SubcommandData> getSubcommands() {
|
|
||||||
return subcommands;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<SubcommandGroupData> getSubcommandGroups() {
|
|
||||||
return subcommandGroups;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return options.isEmpty() && subcommands.isEmpty() && subcommandGroups.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String printUsage() {
|
|
||||||
StringBuilder usage = new StringBuilder();
|
|
||||||
if (!options.isEmpty()) {
|
|
||||||
usage.append("- Usage: /").append(command.getCommandName());
|
|
||||||
for (OptionData option : options) {
|
|
||||||
usage.append(" <").append(option.getName()).append(">");
|
|
||||||
}
|
|
||||||
|
|
||||||
usage.append(printOptions(options, null, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!subcommands.isEmpty()) {
|
|
||||||
for (SubcommandData subcommand : subcommands) {
|
|
||||||
usage.append("- Usage: /").append(command.getCommandName()).append(" ").append(subcommand.getName());
|
|
||||||
|
|
||||||
for (OptionData option : subcommand.getOptions()) {
|
|
||||||
usage.append(" <").append(option.getName()).append(">");
|
|
||||||
}
|
|
||||||
|
|
||||||
usage.append(" (").append(subcommand.getDescription()).append(")");
|
|
||||||
usage.append(printOptions(subcommand.getOptions(), null, false));
|
|
||||||
|
|
||||||
usage.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!subcommandGroups.isEmpty()) {
|
|
||||||
for (SubcommandGroupData subcommandGroup : subcommandGroups) {
|
|
||||||
usage.append("- Subcommand: /").append(command.getCommandName())
|
|
||||||
.append(" ").append(subcommandGroup.getName())
|
|
||||||
.append(" (").append(subcommandGroup.getDescription()).append(")")
|
|
||||||
.append("\n");
|
|
||||||
|
|
||||||
for (SubcommandData subcommand : subcommandGroup.getSubcommands()) {
|
|
||||||
usage.append(" - Usage: /").append(command.getCommandName())
|
|
||||||
.append(" ").append(subcommandGroup.getName())
|
|
||||||
.append(" ").append(subcommand.getName());
|
|
||||||
|
|
||||||
for (OptionData option : subcommand.getOptions()) {
|
|
||||||
usage.append(" <").append(option.getName()).append(">");
|
|
||||||
}
|
|
||||||
|
|
||||||
usage.append(printOptions(subcommand.getOptions(), subcommand.getDescription(), true));
|
|
||||||
|
|
||||||
usage.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isEmpty()) {
|
|
||||||
usage.append("\n\n-# *: required argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
return usage.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String printOptions(List<OptionData> options, String description, boolean group) {
|
|
||||||
StringBuilder usage = new StringBuilder();
|
|
||||||
|
|
||||||
if (description != null) {
|
|
||||||
usage.append(" (").append(description).append(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (OptionData option : options) {
|
|
||||||
usage.append("\n");
|
|
||||||
if (group) usage.append(" ");
|
|
||||||
usage.append(" - ");
|
|
||||||
if (option.isRequired()) {
|
|
||||||
usage.append("*");
|
|
||||||
}
|
|
||||||
usage.append(option.getName()).append(": ").append(option.getDescription());
|
|
||||||
|
|
||||||
if (option.getMinValue() != null) {
|
|
||||||
usage.append(" [Min value: ").append(option.getMinValue().longValue()).append("]");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (option.getMaxValue() != null) {
|
|
||||||
usage.append(" [Max value: ").append(option.getMaxValue().longValue()).append("]");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (option.getMinLength() != null) {
|
|
||||||
usage.append(" [Min length: ").append(option.getMinLength().longValue()).append("]");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (option.getMaxLength() != null) {
|
|
||||||
usage.append(" [Max length: ").append(option.getMaxLength().longValue()).append("]");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<net.dv8tion.jda.api.interactions.commands.Command.Choice> choices = option.getChoices();
|
|
||||||
if (!choices.isEmpty()) {
|
|
||||||
StringJoiner joiner = new StringJoiner(", ");
|
|
||||||
for (net.dv8tion.jda.api.interactions.commands.Command.Choice choice : choices) {
|
|
||||||
joiner.add(choice.getAsString());
|
|
||||||
}
|
|
||||||
|
|
||||||
usage.append(" [Available choices: ").append(joiner).append("]");
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<ChannelType> requiredChannelTypes = option.getChannelTypes();
|
|
||||||
if (!requiredChannelTypes.isEmpty()) {
|
|
||||||
StringJoiner joiner = new StringJoiner(", ");
|
|
||||||
for (ChannelType type : requiredChannelTypes) {
|
|
||||||
joiner.add(type.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
usage.append(" [Required channel types: ").append(joiner).append("]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return usage.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-185
@@ -1,185 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.command.options;
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.command.Command;
|
|
||||||
import net.dv8tion.jda.api.interactions.DiscordLocale;
|
|
||||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.*;
|
|
||||||
import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction;
|
|
||||||
import net.dv8tion.jda.api.interactions.commands.localization.LocalizationMap;
|
|
||||||
import net.dv8tion.jda.api.utils.data.DataObject;
|
|
||||||
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
public class CommandOptionsBuilder implements SlashCommandData {
|
|
||||||
private final Command command;
|
|
||||||
private CommandDataImpl commandData;
|
|
||||||
|
|
||||||
public CommandOptionsBuilder(Command.Type type, Command command) {
|
|
||||||
this.command = command;
|
|
||||||
|
|
||||||
if (type == Command.Type.SLASH) {
|
|
||||||
commandData = (CommandDataImpl) Commands.slash(command.getCommandName(), command.getDescription());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == Command.Type.USER) {
|
|
||||||
commandData = (CommandDataImpl) Commands.user(command.getCommandName());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == Command.Type.MESSAGE) {
|
|
||||||
commandData = (CommandDataImpl) Commands.message(command.getCommandName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandOptions build() {
|
|
||||||
return new CommandOptions(command, commandData);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData setLocalizationFunction(@Nonnull LocalizationFunction localizationFunction) {
|
|
||||||
return commandData.setLocalizationFunction(localizationFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData setName(@Nonnull String name) {
|
|
||||||
return commandData.setName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData setNameLocalization(@Nonnull DiscordLocale locale, @Nonnull String name) {
|
|
||||||
return commandData.setNameLocalization(locale, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData setNameLocalizations(@Nonnull Map<DiscordLocale, String> map) {
|
|
||||||
return commandData.setNameLocalizations(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData setDefaultPermissions(@Nonnull DefaultMemberPermissions permission) {
|
|
||||||
return commandData.setDefaultPermissions(permission);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData setGuildOnly(boolean guildOnly) {
|
|
||||||
return commandData.setGuildOnly(guildOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData setNSFW(boolean nsfw) {
|
|
||||||
return commandData.setNSFW(nsfw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull String getName() {
|
|
||||||
return commandData.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull LocalizationMap getNameLocalizations() {
|
|
||||||
return commandData.getNameLocalizations();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull net.dv8tion.jda.api.interactions.commands.Command.Type getType() {
|
|
||||||
return commandData.getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull DefaultMemberPermissions getDefaultPermissions() {
|
|
||||||
return commandData.getDefaultPermissions();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isGuildOnly() {
|
|
||||||
return commandData.isGuildOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isNSFW() {
|
|
||||||
return commandData.isNSFW();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData setDescription(@Nonnull String description) {
|
|
||||||
return commandData.setDescription(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData setDescriptionLocalization(@Nonnull DiscordLocale locale, @Nonnull String description) {
|
|
||||||
return commandData.setDescriptionLocalization(locale, description);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData setDescriptionLocalizations(@Nonnull Map<DiscordLocale, String> map) {
|
|
||||||
return commandData.setDescriptionLocalizations(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull String getDescription() {
|
|
||||||
return commandData.getDescription();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull LocalizationMap getDescriptionLocalizations() {
|
|
||||||
return commandData.getDescriptionLocalizations();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean removeOptions(@Nonnull Predicate<? super OptionData> condition) {
|
|
||||||
return commandData.removeOptions(condition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean removeSubcommands(@Nonnull Predicate<? super SubcommandData> condition) {
|
|
||||||
return commandData.removeSubcommands(condition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean removeSubcommandGroups(@Nonnull Predicate<? super SubcommandGroupData> condition) {
|
|
||||||
return commandData.removeSubcommandGroups(condition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull List<SubcommandData> getSubcommands() {
|
|
||||||
return commandData.getSubcommands();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull List<SubcommandGroupData> getSubcommandGroups() {
|
|
||||||
return commandData.getSubcommandGroups();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull List<OptionData> getOptions() {
|
|
||||||
return commandData.getOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData addOptions(@Nonnull OptionData... options) {
|
|
||||||
return commandData.addOptions(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData addSubcommands(@Nonnull SubcommandData... subcommands) {
|
|
||||||
return commandData.addSubcommands(subcommands);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull SlashCommandData addSubcommandGroups(@Nonnull SubcommandGroupData... groups) {
|
|
||||||
return commandData.addSubcommandGroups(groups);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull DataObject toData() {
|
|
||||||
return commandData.toData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,6 @@ package me.bobert.netneutrality.core.context;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import io.sentry.Sentry;
|
import io.sentry.Sentry;
|
||||||
import me.bobert.netneutrality.context.command.SlashCommandContext;
|
|
||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.tasks;
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
|
||||||
|
|
||||||
public abstract class AbstractBuiltInTask extends AbstractTask implements BuiltInTask {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInsertable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isExpired() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void replyToInteraction(CommandContext context) {
|
|
||||||
// Task is loaded at runtime, this will never be called
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Lifecycle execute(TaskContext context) {
|
|
||||||
executeTask(context);
|
|
||||||
return Lifecycle.BUILTIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void executeTask(TaskContext context);
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.tasks;
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
public abstract class AbstractPersistableTask extends AbstractTask implements PersistableTask {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInsertable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isExpired() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void replyToInteraction(CommandContext context) {
|
|
||||||
// Task loaded from database, this will never be called
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void insert(CommandContext context) {
|
|
||||||
if (TaskManager.getInstance().hasTask(getId())) {
|
|
||||||
throw new RuntimeException("Cannot insert a task that already exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskManager.getInstance().insert(context, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save() {
|
|
||||||
if (!TaskManager.getInstance().hasTask(getId())) {
|
|
||||||
throw new RuntimeException("Cannot save a task that doesn't exist yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskManager.getInstance().getTaskService().persistTask(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete() {
|
|
||||||
TaskManager.getInstance().getTaskService().unpersistTask(this);
|
|
||||||
TaskManager.getInstance().removeTask(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toPayload() {
|
|
||||||
JSONObject payload = new JSONObject(this);
|
|
||||||
|
|
||||||
return payload.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.tasks;
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public abstract class AbstractTask implements Task {
|
|
||||||
private final OffsetDateTime creationTime;
|
|
||||||
|
|
||||||
public AbstractTask() {
|
|
||||||
creationTime = OffsetDateTime.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public OffsetDateTime getCreationTime() {
|
|
||||||
return creationTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void insert(CommandContext context) {
|
|
||||||
TaskManager.getInstance().insert(context, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
|
|
||||||
AbstractTask that = (AbstractTask) o;
|
|
||||||
return Objects.equals(getId(), that.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hashCode(getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("Task{id=%s, lockId=%s, class=%s, name=%s, creationTime=%s}", getId(), getLockId(), getClass().getSimpleName(), getName(), getCreationTime());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.tasks;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
|
||||||
|
|
||||||
public abstract class GenericCustomIdTask extends AbstractTask {
|
|
||||||
private final String customId;
|
|
||||||
|
|
||||||
public GenericCustomIdTask(String id) {
|
|
||||||
this.customId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return customId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Button createButton() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.tasks;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public abstract class GenericRandomIdTask extends GenericCustomIdTask {
|
|
||||||
public GenericRandomIdTask() {
|
|
||||||
super(UUID.randomUUID().toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.tasks;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
public interface IStepTask {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the type of input expected for a step.
|
|
||||||
*/
|
|
||||||
enum StepType {
|
|
||||||
/**
|
|
||||||
* Expects a string input from the user.
|
|
||||||
*/
|
|
||||||
STRING,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expects a valid role ID for the current guild.
|
|
||||||
* The role must exist in the guild where the command was executed.
|
|
||||||
*/
|
|
||||||
ROLE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expects a valid emoji.
|
|
||||||
*/
|
|
||||||
EMOJI
|
|
||||||
}
|
|
||||||
|
|
||||||
class StepResult {
|
|
||||||
private enum ResultType {
|
|
||||||
SUCCESS, FAILURE
|
|
||||||
}
|
|
||||||
|
|
||||||
private final ResultType type;
|
|
||||||
private final String message;
|
|
||||||
private final Task nextStep;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the result of a step execution. Each step can either succeed, fail, or transition to another step.
|
|
||||||
*/
|
|
||||||
private StepResult(ResultType type, String message, Task nextStep) {
|
|
||||||
this.type = type;
|
|
||||||
this.message = message;
|
|
||||||
this.nextStep = nextStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that the step was completed successfully, with an optional follow-up step.
|
|
||||||
*
|
|
||||||
* @param message the success message
|
|
||||||
* @param nextStep the next step in the workflow, or null if this is the final step
|
|
||||||
* @return a successful result
|
|
||||||
*/
|
|
||||||
public static StepResult success(String message, Task nextStep) {
|
|
||||||
return new StepResult(ResultType.SUCCESS, message, nextStep);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that the step was completed successfully.
|
|
||||||
*
|
|
||||||
* @param message the success message
|
|
||||||
* @return a successful result without a next step
|
|
||||||
*/
|
|
||||||
public static StepResult success(String message) {
|
|
||||||
return new StepResult(ResultType.SUCCESS, message, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that the step has failed.
|
|
||||||
*
|
|
||||||
* @param message the failure message
|
|
||||||
* @return a failed result
|
|
||||||
*/
|
|
||||||
public static StepResult failure(String message) {
|
|
||||||
return new StepResult(ResultType.FAILURE, message, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves directly to the next step without displaying a message.
|
|
||||||
*
|
|
||||||
* @param nextTask the next task in the workflow
|
|
||||||
* @return a successful result that advances to the next step
|
|
||||||
*/
|
|
||||||
public static StepResult next(Task nextTask) {
|
|
||||||
return new StepResult(ResultType.SUCCESS, null, nextTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the message associated with the step result.
|
|
||||||
*
|
|
||||||
* @return the result message, or null if there is no message
|
|
||||||
*/
|
|
||||||
public String getMessage() {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the next step in the task workflow.
|
|
||||||
*
|
|
||||||
* @return the next step, or null if this is the last step
|
|
||||||
*/
|
|
||||||
public Task getNextStep() {
|
|
||||||
return nextStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the step execution was successful.
|
|
||||||
*
|
|
||||||
* @return true if the step was successful, false otherwise
|
|
||||||
*/
|
|
||||||
public boolean isSuccess() {
|
|
||||||
return type == ResultType.SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the type of step input expected.
|
|
||||||
*
|
|
||||||
* @return the step type
|
|
||||||
*/
|
|
||||||
StepType getStepType();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a general description of the step. This will be displayed before asking the question.
|
|
||||||
*
|
|
||||||
* @return the step description
|
|
||||||
*/
|
|
||||||
String getStepDescription();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the specific question for this step.
|
|
||||||
*
|
|
||||||
* @return the step question
|
|
||||||
*/
|
|
||||||
String getStepQuestion();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the step using the provided answer.
|
|
||||||
*
|
|
||||||
* @param answer the user's input, validated against the expected step type
|
|
||||||
* @return the result of executing this step
|
|
||||||
*/
|
|
||||||
StepResult executeStep(Object answer);
|
|
||||||
}
|
|
||||||
@@ -1,169 +0,0 @@
|
|||||||
package me.bobert.netneutrality.core.tasks.impl;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
|
||||||
import me.bobert.netneutrality.core.context.MessageContext;
|
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
|
||||||
import me.bobert.netneutrality.core.tasks.AbstractTask;
|
|
||||||
import me.bobert.netneutrality.core.tasks.IStepTask;
|
|
||||||
import me.bobert.netneutrality.core.tasks.TaskManager;
|
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
|
||||||
import net.fellbaum.jemoji.Emoji;
|
|
||||||
import net.fellbaum.jemoji.EmojiManager;
|
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a task that consists of multiple sequential steps. The task starts with an initial message (question)
|
|
||||||
* and expects a user response. Each step can lead to another step, forming a workflow.
|
|
||||||
*/
|
|
||||||
public abstract class StepTask extends AbstractTask implements IStepTask {
|
|
||||||
private final Object stepLock = new Object();
|
|
||||||
private CommandContext commandContext;
|
|
||||||
private Guild guild;
|
|
||||||
private String id = UUID.randomUUID().toString();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInsertable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Guild getGuild() {
|
|
||||||
return guild;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void replyToInteraction(CommandContext context) {
|
|
||||||
synchronized (stepLock) {
|
|
||||||
this.commandContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.isFromGuild()) {
|
|
||||||
guild = context.getGuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (guild == null && getStepType() == StepType.ROLE) {
|
|
||||||
throw new IllegalArgumentException("Step task is of type role but it was inserted in a non-guild context");
|
|
||||||
}
|
|
||||||
|
|
||||||
context.replyEphemeral("Please follow the instructions sent in DM.");
|
|
||||||
context.sendMessageInPrivate(getStepDescription() + "\n\n" + getStepQuestion(),
|
|
||||||
asyncContext -> assignId(asyncContext.getMessageId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Lifecycle execute(TaskContext context) {
|
|
||||||
synchronized (stepLock) {
|
|
||||||
if (!context.getDiscordUser().equals(commandContext.getDiscordUser())) {
|
|
||||||
return Lifecycle.KEEP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context instanceof MessageContext messageContext) {
|
|
||||||
Message message = messageContext.getMessage();
|
|
||||||
String input = message.getContentRaw();
|
|
||||||
|
|
||||||
|
|
||||||
Object answer = validateInput(context, input);
|
|
||||||
if (answer == null) {
|
|
||||||
return Lifecycle.KEEP;
|
|
||||||
}
|
|
||||||
|
|
||||||
StepResult result = executeStep(answer);
|
|
||||||
if (!result.isSuccess()) {
|
|
||||||
context.replyEphemeral(result.getMessage());
|
|
||||||
return Lifecycle.KEEP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.getMessage() != null) {
|
|
||||||
context.replyEphemeral(result.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.getNextStep() != null) {
|
|
||||||
result.getNextStep().insert(commandContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Lifecycle.REMOVE_SELF;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Step task is not of type MessageContext");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isExpired() {
|
|
||||||
// is it really needed to expire this type of task?
|
|
||||||
return getCreationTime().plusMinutes(60).isBefore(OffsetDateTime.now());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Button createButton() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the user input against the expected step type.
|
|
||||||
*
|
|
||||||
* @param context the task execution context
|
|
||||||
* @param input the user-provided input
|
|
||||||
* @return the parsed input if valid, or null if invalid
|
|
||||||
*/
|
|
||||||
private Object validateInput(TaskContext context, String input) {
|
|
||||||
switch (getStepType()) {
|
|
||||||
case ROLE -> {
|
|
||||||
try {
|
|
||||||
Role role = guild.getRoleById(input);
|
|
||||||
if (role == null) {
|
|
||||||
context.replyEphemeral("The role doesn't exist");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return role;
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
context.replyEphemeral("Not a valid role ID");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case EMOJI -> {
|
|
||||||
Optional<Emoji> parsed = EmojiManager.getEmoji(input);
|
|
||||||
|
|
||||||
if (parsed.isPresent()) {
|
|
||||||
return parsed.get().getEmoji();
|
|
||||||
}
|
|
||||||
|
|
||||||
context.replyEphemeral("Not a valid emoji");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
case STRING -> {
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
default -> throw new IllegalStateException("Unknown step type: " + getStepType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assignId(String newId) {
|
|
||||||
if (newId == null || newId.isBlank()) {
|
|
||||||
throw new IllegalArgumentException("Task ID cannot be null or empty.");
|
|
||||||
}
|
|
||||||
|
|
||||||
String oldId = id;
|
|
||||||
synchronized (this) {
|
|
||||||
this.id = newId;
|
|
||||||
TaskManager.getInstance().activateTask(this, oldId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,6 @@ import me.bobert.netneutrality.utils.MessageFunction;
|
|||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import net.dv8tion.jda.api.components.buttons.ButtonStyle;
|
import net.dv8tion.jda.api.components.buttons.ButtonStyle;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle;
|
|
||||||
|
|
||||||
public class LoadTrackFromPlaylistTask extends AcceptButton<LoadPlaylistTask> {
|
public class LoadTrackFromPlaylistTask extends AcceptButton<LoadPlaylistTask> {
|
||||||
private final AudioTrack track;
|
private final AudioTrack track;
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
package me.bobert.netneutrality.thread;
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import me.bobert.netneutrality.music.MusicManager;
|
|
||||||
import me.bobert.netneutrality.music.TrackScheduler;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
public class MusicManagerCleanupThread implements Runnable {
|
|
||||||
private static final Logger logger = LogManager.getLogger(MusicManagerCleanupThread.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
for (MusicManager manager : MusicManager.getManagers()) {
|
|
||||||
processManager(manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error("Interrupted while running MusicManagerCleanupThread", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processManager(MusicManager manager) throws InterruptedException {
|
|
||||||
TrackScheduler scheduler = manager.getScheduler();
|
|
||||||
|
|
||||||
// Context is still attached after bot is disconnected, the bot might have been kicked from the channel
|
|
||||||
if (scheduler.getContext() != null && !manager.isConnected()) {
|
|
||||||
manager.disconnect();
|
|
||||||
manager.getQueueManager().clearQueue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user