Added the Sheepstar Core V1

This commit is contained in:
Mathias Wagner 2022-09-06 16:18:49 +02:00
parent 2e16cfa2cb
commit a58b73ba32
134 changed files with 9349 additions and 0 deletions

View File

@ -0,0 +1,17 @@
name: Java CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK
uses: actions/setup-java@v2
with:
java-version: '8'
distribution: 'adopt'
- name: Build with Maven
run: mvn --batch-mode --update-snapshots verify

View File

@ -0,0 +1,42 @@
name: Upload the latest sheepstar release
on:
push:
branches: [ master ]
jobs:
create:
name: "Creates the newest sheepstar release"
runs-on: "ubuntu-latest"
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
- name: Setup java
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: '8'
- name: Build
run: "mvn compile assembly:single"
- name: Create Javadoc
run: |
mvn javadoc:javadoc
zip -r docs.zip ./target/site
- name: Get version
id: get_version
run: echo "::set-output name=version::$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' exec:exec)"
- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: ${{ steps.get_version.outputs.version }}
prerelease: false
title: Release ${{ steps.get_version.outputs.version }}
files: |
./target/*.jar
./docs.zip

5
SheepstarCoreV1/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Project exclude paths
/target/
/env
/.idea/
/SheepstarCore.iml

98
SheepstarCoreV1/README.md Normal file
View File

@ -0,0 +1,98 @@
<h1 align="center">Sheepstar Core</h1>
## About The Project
This is the official Sheepstar Core. It was written with java and made to run with the JDA. Have fun during programming
your own modules :p
## Getting Started
### Installation
1. Create a new project in your IDE
2. Import the dependency from https://jitpack.io/#sheepstar-dc/SheepstarCore
3. Create an `.env` folder (or another folder in which you want to load the runtime)
4. Create a `config.json` file in your `.env` folder and replace it to your needs
```json
{
"token": "the discord bot token",
"api_key": "the key of the sheepstar api",
"api_url": "https://api.sheepstar.xyz",
"moduleDirectory": "modules",
"mysql": {
"hostname": "localhost",
"username": "username",
"password": "password",
"database": "database"
},
"commands": {
"enable_ping_feature": true,
"enable_prefix_feature": true,
"enable_slash_feature": true,
"debug_guild": "guildID / leave empty to set global"
},
"permissions": {
"BOT_OWNER": [
"357214370188492802",
"386242172632170496"
],
"SUPPORTER": {
"guildID": "846497208086167602",
"roleID": "860823465329295380"
}
},
"activities": [
{
"type": "WATCHING",
"name": "discord.gg/dAe7BPsHZc"
},
{
"type": "LISTENING",
"name": "/help"
},
{
"type": "WATCHING",
"name": "sheepstar.xyz"
}
],
"pools": [
{
"name": "SR-PreparePool",
"cores": 16
},
{
"name": "SR-CommandPool",
"cores": 8
},
{
"name": "SR-ListenerPool",
"cores": 8
},
{
"name": "SR-ActionPool",
"cores": 4
}
]
}
```
5. Add a `module.yml` file into your resources
```yaml
main: xyz.sheepstar.exampleModule.Bootstrap # your main class
name: example module # your module name
author: Mathias Wagner # the name of the author
```
### Optional: Instant reloading (Only works in IntelliJ)
#### If you want to, you can create a configuration that lets you update the changes directly without restarting (in most cases)
1. Go to `Project Settings` > `Artifacts` and create a new empty artifact
2. Add `compile output` into your `.jar` file
3. Change the output directory to the `modules` directory (it should be located in your runtime folder. if not, create
one.)
4. Apply the settings and create a new `Application`-configuration
5. Change the main-class to `xyz.sheepstar.core.SheepstarCore`
6. Click on `Modify options` > `Add before launch task` > `Build artifact` and choose your created artifact
7. Change the working directory to your runtime folder
8. Add `-cf config.json` to your program arguments
9. Ready! Click on the debug-icon to start your module, make a change and click on the build-icon to try it

177
SheepstarCoreV1/pom.xml Normal file
View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>xyz.sheepstar</groupId>
<artifactId>SheepstarCore</artifactId>
<version>beta1.0.2</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>central</id>
<name>bintray</name>
<url>https://jcenter.bintray.com</url>
</repository>
<repository>
<id>dv8tion</id>
<name>m2-dv8tion</name>
<url>https://m2.dv8tion.net/releases</url>
</repository>
<repository>
<id>jitpack</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<id>maven_central</id>
<name>Maven Central</name>
<url>https://repo.maven.apache.org/maven2/</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>xyz.sheepstar.core.SheepstarCore</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- SQLToolkit for MySQL-->
<dependency>
<groupId>com.github.gnmyt</groupId>
<artifactId>sqltoolkit</artifactId>
<version>v2.0.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- JDA (The bot itself) -->
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>4.4.0_350</version>
</dependency>
<!-- Commons CLI (apache-cli) -->
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
<!-- Commons IO -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
</dependency>
<!-- Commons lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- Logger API (api) -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
<!-- Logger API (log4j12) -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.32</version>
</dependency>
<!-- Logger API Extras -->
<dependency>
<groupId>log4j</groupId>
<artifactId>apache-log4j-extras</artifactId>
<version>1.2.17</version>
</dependency>
<!-- Colorful console log -->
<dependency>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-log</artifactId>
<version>0.20.1</version>
</dependency>
<!-- FasterXML for YAML Configurations -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.13.0</version>
</dependency>
<!-- FasterXML Databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
<!-- HTTP Client -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.2</version>
</dependency>
<!-- Guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
<!-- Reflections Library -->
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
</dependency>
<!-- Simple time formatter -->
<dependency>
<groupId>org.ocpsoft.prettytime</groupId>
<artifactId>prettytime</artifactId>
<version>5.0.2.Final</version>
</dependency>
<!-- Discord webhook library -->
<dependency>
<groupId>club.minnced</groupId>
<artifactId>discord-webhooks</artifactId>
<version>0.7.2</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,78 @@
package xyz.sheepstar.core;
import xyz.sheepstar.core.commands.console.*;
import xyz.sheepstar.core.commands.general.HelpCommand;
import xyz.sheepstar.core.commands.general.*;
import xyz.sheepstar.util.SheepstarImpl;
public class SheepstarCore {
private static SheepstarImpl sheepstar;
public static void main(String[] args) throws Exception {
sheepstar = new SheepstarImpl(args);
sheepstar.init();
registerConsoleCommands();
registerGeneralCommands();
Thread.sleep(5000);
sheepstar.finish();
}
/**
* Registers all general commands (all commands in the general-package)
*/
public static void registerGeneralCommands() {
sheepstar.registerGeneralCommand(new ListSettingsCommand());
sheepstar.registerGeneralCommand(new SetSettingCommand());
sheepstar.registerGeneralCommand(new BuyCommand());
sheepstar.registerGeneralCommand(new ShopCommand());
sheepstar.registerGeneralCommand(new SwitchLanguageCommand());
sheepstar.registerGeneralCommand(new ShowCoinsCommand());
sheepstar.registerGeneralCommand(new HelpCommand());
sheepstar.registerGeneralCommand(new ListCommandsCommand());
sheepstar.registerGeneralCommand(new InfoCommand());
sheepstar.registerGeneralCommand(new DisableModuleCommand());
sheepstar.registerGeneralCommand(new EnableModuleCommand());
sheepstar.registerGeneralCommand(new ShowPrefixCommand());
sheepstar.registerGeneralCommand(new RedeemCommand());
sheepstar.registerGeneralCommand(new PingCommand());
}
/**
* Registers all console commands (all commands in the console package)
*/
public static void registerConsoleCommands() {
sheepstar.getConsoleManager().register(new GetSettingCommand());
sheepstar.getConsoleManager().register(new GetSettingInfoCommand());
sheepstar.getConsoleManager().register(new InsertSettingInfoCommand());
sheepstar.getConsoleManager().register(new UpdateSettingCommand());
sheepstar.getConsoleManager().register(new xyz.sheepstar.core.commands.console.HelpCommand());
sheepstar.getConsoleManager().register(new LoadModuleCommand());
sheepstar.getConsoleManager().register(new QueryCommand());
sheepstar.getConsoleManager().register(new ShutdownCommand());
sheepstar.getConsoleManager().register(new TranslationCommand());
}
/**
* Gets the sheepstar api object
*
* @return the sheepstar api object
*/
public static SheepstarImpl getSheepstar() {
return sheepstar;
}
}

View File

@ -0,0 +1,37 @@
package xyz.sheepstar.core.commands.console;
import net.dv8tion.jda.api.entities.Guild;
import org.slf4j.Logger;
import xyz.sheepstar.util.console.ConsoleCommand;
import xyz.sheepstar.util.log.LogManager;
import java.util.Arrays;
import java.util.List;
public class GetSettingCommand extends ConsoleCommand {
private final Logger LOG = LogManager.getLog(GetSettingCommand.class);
@Override
public List<String> getAlias() {
return Arrays.asList("getsetting", "gsg", "gst");
}
@Override
public void usage() {
usage("moduleName", -1, true);
usage("guildID", -1, true);
usage("setting", -1, true);
}
@Override
public void onExecute(String[] args) {
Guild guild = api.getJDA().getGuildById(args[1]);
if (guild == null) {
LOG.error("The guild does not exist");
return;
}
String setting = api.getBotManager().getSettingsManager().getSetting(guild, args[0], args[2]).toString();
LOG.info("The setting {} of the guild {} has got the value {}", args[2], guild.getName(), setting);
}
}

View File

@ -0,0 +1,35 @@
package xyz.sheepstar.core.commands.console;
import org.slf4j.Logger;
import xyz.sheepstar.util.console.ConsoleCommand;
import xyz.sheepstar.util.log.LogManager;
import java.util.Arrays;
import java.util.List;
public class GetSettingInfoCommand extends ConsoleCommand {
private final Logger LOG = LogManager.getLog(GetSettingInfoCommand.class);
@Override
public List<String> getAlias() {
return Arrays.asList("gsettingsinfo", "getsettingsinfo", "gsi", "si");
}
@Override
public void usage() {
usage("moduleName", -1, true);
usage("setting", -1, true);
}
@Override
public void onExecute(String[] args) {
if (!api.getBotManager().getSettingsInfoManager().existsInfo(args[0], args[1])) {
LOG.error("The provided info does not exists");
return;
}
String description = api.getBotManager().getSettingsInfoManager().getDescription(args[0], args[1]);
String defaultValue = api.getBotManager().getSettingsInfoManager().getDefaultValue(args[0], args[1]);
LOG.info("The description of the info says {} and the default value says {}", description, defaultValue);
}
}

View File

@ -0,0 +1,28 @@
package xyz.sheepstar.core.commands.console;
import org.slf4j.Logger;
import xyz.sheepstar.util.console.ConsoleCommand;
import xyz.sheepstar.util.log.LogManager;
import java.util.Arrays;
import java.util.List;
public class HelpCommand extends ConsoleCommand {
private final Logger LOG = LogManager.getLog(HelpCommand.class);
@Override
public List<String> getAlias() {
return Arrays.asList("help", "listcommands", "commands");
}
@Override
public void onExecute(String[] args) {
StringBuilder help = new StringBuilder();
for (ConsoleCommand command : api.getConsoleManager().getRegisteredCommands()) {
if (!help.toString().isEmpty()) help.append(" ");
help.append(command.getAlias().get(0));
}
LOG.info("Current commands available: {}", help);
}
}

View File

@ -0,0 +1,33 @@
package xyz.sheepstar.core.commands.console;
import org.slf4j.Logger;
import xyz.sheepstar.util.console.ConsoleCommand;
import xyz.sheepstar.util.log.LogManager;
import java.util.Arrays;
import java.util.List;
public class InsertSettingInfoCommand extends ConsoleCommand {
private final Logger LOG = LogManager.getLog(InsertSettingInfoCommand.class);
@Override
public List<String> getAlias() {
return Arrays.asList("isettingsinfo", "insertsettingsinfo", "isi");
}
@Override
public void usage() {
usage("moduleName", -1, true);
usage("settingString", -1, true);
usage("descriptionString", -1, true);
usage("defaultValue", -1, true);
usage("allowedValues", -1, true);
}
@Override
public void onExecute(String[] args) {
api.getBotManager().getSettingsInfoManager().createInfo(args[0], args[1], args[2], args[3], args[4]);
LOG.info("The info got successfully created");
}
}

View File

@ -0,0 +1,25 @@
package xyz.sheepstar.core.commands.console;
import xyz.sheepstar.util.console.ConsoleCommand;
import java.util.Arrays;
import java.util.List;
public class LoadModuleCommand extends ConsoleCommand {
@Override
public List<String> getAlias() {
return Arrays.asList("enable", "load");
}
@Override
public void usage() {
usage("moduleName", -1, true);
}
@Override
public void onExecute(String[] args) {
api.getModuleManager().loadModule(args[0] + ".jar");
}
}

View File

@ -0,0 +1,43 @@
package xyz.sheepstar.core.commands.console;
import org.slf4j.Logger;
import xyz.sheepstar.util.console.ConsoleCommand;
import xyz.sheepstar.util.log.LogManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class QueryCommand extends ConsoleCommand {
private final Logger LOG = LogManager.getLog(QueryCommand.class);
@Override
public List<String> getAlias() {
return Arrays.asList("query", "result", "runquery");
}
@Override
public void onExecute(String[] args) {
if (args.length == 0) {
LOG.error("You need to provide a query");
return;
}
StringBuilder query = new StringBuilder();
for (String current : args) {
if (!query.toString().isEmpty()) query.append(" ");
query.append(current);
}
ArrayList<HashMap<String, Object>> result = api.getDatabase().getResult(query.toString()).getList();
System.out.println("-=============== QUERY START ===============-");
result.forEach((map) -> {
System.out.println("--============= RESULT START ==============--");
map.forEach((key, val) -> System.out.println(key + ": " + val));
System.out.println("--============== RESULT END ===============--");
});
System.out.println("-============== QUERY END ==================-");
}
}

View File

@ -0,0 +1,28 @@
package xyz.sheepstar.core.commands.console;
import xyz.sheepstar.util.console.ConsoleCommand;
import java.util.Arrays;
import java.util.List;
public class ShutdownCommand extends ConsoleCommand {
@Override
public List<String> getAlias() {
return Arrays.asList("shutdown", "stop", "end", "exit");
}
@Override
public void onExecute(String[] args) {
StringBuilder msg = new StringBuilder("User requested a shutdown");
if (args.length >= 1) {
msg = new StringBuilder();
for (String current : args) {
if (!msg.toString().isEmpty()) msg.append(" ");
msg.append(current);
}
}
api.shutdown(msg.toString());
}
}

View File

@ -0,0 +1,35 @@
package xyz.sheepstar.core.commands.console;
import org.slf4j.Logger;
import xyz.sheepstar.util.console.ConsoleCommand;
import xyz.sheepstar.util.log.LogManager;
import java.util.Arrays;
import java.util.List;
public class TranslationCommand extends ConsoleCommand {
private final Logger LOG = LogManager.getLog(TranslationCommand.class);
@Override
public List<String> getAlias() {
return Arrays.asList("translate", "inserttranslation", "tr");
}
@Override
public void onExecute(String[] args) {
if (args.length <= 2) {
LOG.error("You need to provide a translationString, a language code and a translation");
return;
}
StringBuilder translated = new StringBuilder();
for (int i = 2; i < args.length; i++) {
if (!translated.toString().isEmpty()) translated.append(" ");
translated.append(args[i]);
}
api.insertTranslation(args[0], args[1], translated.toString());
LOG.info("Translation inserted successfully");
}
}

View File

@ -0,0 +1,39 @@
package xyz.sheepstar.core.commands.console;
import net.dv8tion.jda.api.entities.Guild;
import org.slf4j.Logger;
import xyz.sheepstar.util.console.ConsoleCommand;
import xyz.sheepstar.util.log.LogManager;
import java.util.Arrays;
import java.util.List;
public class UpdateSettingCommand extends ConsoleCommand {
private final Logger LOG = LogManager.getLog(UpdateSettingCommand.class);
@Override
public List<String> getAlias() {
return Arrays.asList("updatesetting", "usg", "ust");
}
@Override
public void usage() {
usage("moduleName", -1, true);
usage("guildID", -1, true);
usage("setting", -1, true);
usage("value", -1, true);
}
@Override
public void onExecute(String[] args) {
Guild guild = api.getJDA().getGuildById(args[1]);
if (guild == null) {
LOG.error("The guild does not exist");
return;
}
api.getBotManager().getSettingsManager().updateSetting(guild, args[0], args[2], args[3]);
LOG.info("Setting updated successfully");
}
}

View File

@ -0,0 +1,47 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.PublicCommandException;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.bot.manager.sql.GuildManager;
import xyz.sheepstar.util.bot.permission.PermissionNode;
import xyz.sheepstar.util.http.client.entities.Article;
import xyz.sheepstar.util.http.client.objects.ArticleObject;
import xyz.sheepstar.util.http.client.objects.ShopObject;
@CommandMeta(aliases = {"buy", "buyarticle"}, permission = PermissionNode.ADMINISTRATOR, description = "Buys an article")
public class BuyCommand extends GeneralGuildCommand {
private final ShopObject itemManager = api.getShop();
private final ArticleObject articleManager = api.getArticles();
private final GuildManager guildManager = api.getBotManager().getGuildManager();
@Override
public void usage() {
usage("article", "The ID of the article you want to buy").required(true).add();
usage("moduleName", "The module you want to use to buy this item").add();
}
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
Article article = articleManager.findArticle(args.exists("moduleName") ? moduleName : "main", args.getString("article")).complete();
if (article == null) throw new PublicCommandException("bot.article.not_existing");
int currentMoney = guildManager.getCoinsInt(event.getGuild());
int neededMoney = article.getArticlePrice();
if (currentMoney < neededMoney) throw new PublicCommandException("bot.not_enough_money");
Integer code = itemManager.activateItem(article.getID() + "", event.getGuild()).complete();
if (code == 400) throw new PublicCommandException("bot.article.reached_limit");
guildManager.updateCoins(event.getGuild(), String.valueOf(currentMoney - neededMoney));
event.success("bot.article_activated", article.getArticleName());
}
}

View File

@ -0,0 +1,20 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.PublicCommandException;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.bot.permission.PermissionNode;
@CommandMeta(aliases = "module", subAliases = "disable", permission = PermissionNode.ADMINISTRATOR, description = "Disables a module")
public class DisableModuleCommand extends GeneralGuildCommand {
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
if (!moduleManager.isEnabled(event.getGuild(), moduleName.toLowerCase()))
throw new PublicCommandException("bot.module.not_enabled");
moduleManager.disableModule(event.getGuild(), moduleName.toLowerCase());
event.success("bot.module_disabled");
}
}

View File

@ -0,0 +1,33 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.PublicCommandException;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.bot.permission.PermissionNode;
@CommandMeta(aliases = "module", subAliases = "enable", permission = PermissionNode.ADMINISTRATOR, description = "Enables a module")
public class EnableModuleCommand extends GeneralGuildCommand {
@Override
public void generalUsage() {
usage("prefix", "The prefix you want to use in this module").add();
}
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
if (moduleManager.isEnabled(event.getGuild(), moduleName.toLowerCase()))
throw new PublicCommandException("bot.module.already_enabled");
if (api.getModuleManager().getActivated_modules().get(moduleName) == null)
throw new PublicCommandException("bot.module.does_not_exist");
String prefix = args.exists("prefix") ? args.getString("prefix").replace(" ", "") : "!";
if (prefix.length() > 5) prefix = prefix.substring(0, 5);
moduleManager.enableModule(event.getGuild(), moduleName.toLowerCase(), prefix);
event.success("bot.module_enabled", moduleName.toLowerCase(), prefix.toLowerCase());
}
}

View File

@ -0,0 +1,21 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
@CommandMeta(aliases = "help", description = "Shows a quick help of the sheepstar bot")
public class HelpCommand extends GeneralGuildCommand {
@Override
public void usage() {
}
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
event.primary("bot.help");
}
}

View File

@ -0,0 +1,20 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
@CommandMeta(aliases = "info", description = "Shows the info of the bot")
public class InfoCommand extends GeneralGuildCommand {
@Override
public void usage() {
}
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
event.primary("bot.info");
}
}

View File

@ -0,0 +1,60 @@
package xyz.sheepstar.core.commands.general;
import com.google.common.base.CaseFormat;
import xyz.sheepstar.util.bot.builder.message.MessageField;
import xyz.sheepstar.util.bot.builder.message.MessageType;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildCommand;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.internal.manager.ListenerManager;
import java.util.ArrayList;
import java.util.Arrays;
@CommandMeta(aliases = "commands", description = "Shows you all commands of this bot")
public class ListCommandsCommand extends GeneralGuildCommand {
ListenerManager listenerManager = api.getListenerManager();
@Override
public void usage() {
usage("moduleName", "The name of the module you want to get commands from").add();
}
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
ArrayList<MessageField> fields = new ArrayList<>();
for (GuildCommand command : listenerManager.getCommands()) {
CommandMeta meta = command.getClass().getAnnotation(CommandMeta.class);
if (command instanceof GeneralGuildCommand && args.exists("moduleName")) continue;
if (!(command instanceof GeneralGuildCommand) && !args.exists("moduleName")) continue;
if (!(command instanceof GeneralGuildCommand) && args.exists("moduleName")
&& !api.getModuleName(command.getClass().getName()).equals(args.getString("moduleName"))) continue;
StringBuilder aliases = new StringBuilder();
Arrays.stream(meta.aliases()).forEach(alias -> {
if (!aliases.toString().isEmpty()) aliases.append(", ");
aliases.append(alias);
});
fields.add(new MessageField(":gear: " + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, meta.aliases()[0] + " "
+ (meta.subAliases().length >= 1 ? meta.subAliases()[0] : "")),
"**" + translate("bot.description", event.getLanguage()) + "**: " + meta.description(),
"**" + translate("bot.aliases", event.getLanguage())
+ "**: " + aliases + " " + (meta.subAliases().length >= 1 ? meta.subAliases()[0] : "")));
}
if (fields.isEmpty())
fields.add(new MessageField(":warning: " + translate("bot.not_found", event.getLanguage()),
translate("bot.module_not_found", event.getLanguage())));
event.custom(MessageType.PRIMARY, "bot.commands", fields);
}
}

View File

@ -0,0 +1,35 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.builder.message.MessageField;
import xyz.sheepstar.util.bot.builder.message.MessageType;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.bot.manager.sql.SettingsInfoManager;
import xyz.sheepstar.util.bot.manager.sql.SettingsManager;
import xyz.sheepstar.util.bot.permission.PermissionNode;
import java.util.ArrayList;
@CommandMeta(aliases = {"settings", "listsettings"}, permission = PermissionNode.ADMINISTRATOR, description = "Lists all settings from the current guild")
public class ListSettingsCommand extends GeneralGuildCommand {
private final SettingsManager settingsManager = api.getBotManager().getSettingsManager();
private final SettingsInfoManager settingsInfoManager = api.getBotManager().getSettingsInfoManager();
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
ArrayList<MessageField> fields = new ArrayList<>();
settingsInfoManager.getSettings(moduleName).forEach(setting -> {
String value = settingsManager.getSettingString(event.getGuild(), moduleName, (String) setting.get("settingString"));
if (value.equals("yes") || value.equals("no")) value = translate("bot." + value, event.getLanguage());
fields.add(new MessageField(String.format(":gear: `%s`", setting.get("settingString")),
translate((String) setting.get("descriptionString"), event.getLanguage()),
translate("bot.current", event.getLanguage()) + ": **" + value + "**"));
});
event.custom(MessageType.PRIMARY, "bot.module_settings", fields, moduleName);
}
}

View File

@ -0,0 +1,21 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
@CommandMeta(aliases = {"ping", "botping", "gwping"}, description = "Shows you the current ping of the bot")
public class PingCommand extends GeneralGuildCommand {
@Override
public void usage() {
}
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
event.primary("bot.ping", jda.getGatewayPing());
}
}

View File

@ -0,0 +1,36 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.PublicCommandException;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.bot.permission.PermissionNode;
import xyz.sheepstar.util.http.client.entities.Gift;
import xyz.sheepstar.util.http.client.objects.ArticleObject;
import xyz.sheepstar.util.http.client.objects.GiftObject;
@CommandMeta(aliases = "redeem", permission = PermissionNode.ADMINISTRATOR, description = "Redeems a gift code to the server")
public class RedeemCommand extends GeneralGuildCommand {
private final GiftObject giftManager = api.getGifts();
private final ArticleObject articleManager = api.getArticles();
@Override
public void usage() {
usage("giftID", "The gift code").required(true).add();
}
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
Gift info = giftManager.getInfo(args.getString("giftID")).complete();
Integer code = giftManager.redeemGift(args.getString("giftID"), event.getGuild()).complete();
if (code == 400) throw new PublicCommandException("bot.article.reached_limit");
if (code == 404) throw new PublicCommandException("bot.gift.not_found");
event.success("bot.gift.redeemed_successfully", articleManager.getArticle(info.getArticleId()).complete().getArticleName());
}
}

View File

@ -0,0 +1,37 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.PublicCommandException;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.bot.manager.sql.SettingsInfoManager;
import xyz.sheepstar.util.bot.manager.sql.SettingsManager;
import xyz.sheepstar.util.bot.permission.PermissionNode;
@CommandMeta(aliases = {"setting", "setsetting"}, permission = PermissionNode.ADMINISTRATOR, description = "Sets a setting in a guild")
public class SetSettingCommand extends GeneralGuildCommand {
private final SettingsManager settingsManager = api.getBotManager().getSettingsManager();
private final SettingsInfoManager settingsInfoManager = api.getBotManager().getSettingsInfoManager();
@Override
public void generalUsage() {
usage("setting", "The setting key").required(true).add();
usage("value", "The setting value").required(true).add();
}
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
if (!settingsInfoManager.existsInfo(moduleName, args.getString("setting")))
throw new PublicCommandException("bot.setting.not_existing");
if (!settingsInfoManager.isAllowed(moduleName, args.getString("setting"), args.getString("value")))
throw new PublicCommandException("bot.setting.value_not_allowed",
settingsInfoManager.getAllowedValuesPretty(moduleName, args.getString("setting")));
settingsManager.updateSetting(event.getGuild(), moduleName, args.getString("setting"), args.getString("value"));
event.success("bot.setting_updated", args.getString("setting"), args.getString("value"));
}
}

View File

@ -0,0 +1,67 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.builder.message.MessageField;
import xyz.sheepstar.util.bot.builder.message.MessageType;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.bot.emote.INTERN_EMOTE;
import xyz.sheepstar.util.bot.permission.PermissionNode;
import xyz.sheepstar.util.http.client.entities.Article;
import xyz.sheepstar.util.http.client.entities.ShopItem;
import xyz.sheepstar.util.http.client.objects.ArticleObject;
import xyz.sheepstar.util.http.client.objects.ShopObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@CommandMeta(aliases = {"shop", "listarticles"}, permission = PermissionNode.ADMINISTRATOR, description = "Shows all articles you can buy")
public class ShopCommand extends GeneralGuildCommand {
private final ShopObject itemManager = api.getShop();
private final ArticleObject articleManager = api.getArticles();
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
List<Article> items = articleManager.getArticles(moduleName).complete();
if (items == null) throw new Exception("Could not process request");
ArrayList<MessageField> fields = new ArrayList<>();
List<ShopItem> owned_items = itemManager.getItems(event.getGuild()).complete();
HashMap<Integer, Integer> ownedArticles = sortOwnedArticles(owned_items);
items.forEach(item -> {
int currentCount = ownedArticles.get(item.getID()) != null ? ownedArticles.get(item.getID()) : 0;
String bought = currentCount == item.getMaxOwnCount() ? ":white_check_mark:" : currentCount + "/" + item.getMaxOwnCount();
fields.add(new MessageField(String.format(":shopping_cart: `%s` | %s", item.getArticleName(), bought), item.getArticleDescription(),
translate("bot.article_id", event.getLanguage()) + ": **" + item.getArticleId() + "**",
translate("bot.article_price", event.getLanguage()) + ": **" + item.getArticlePrice() + "** " + getEmoteString(INTERN_EMOTE.STAR_COIN)));
});
event.custom(MessageType.PRIMARY, "bot.shop", fields, moduleName);
}
/**
* Returns a HashMap with the article ID as key and the amount of owned articles as value
*
* @param items The list of owned items
* @return the HashMap
*/
public HashMap<Integer, Integer> sortOwnedArticles(List<ShopItem> items) {
HashMap<Integer, Integer> ownedArticles = new HashMap<>();
items.forEach(item -> {
Integer articleID = Integer.valueOf(item.getArticleId());
if (ownedArticles.containsKey(articleID)) {
ownedArticles.put(articleID, ownedArticles.get(articleID) + 1);
} else ownedArticles.put(articleID, 1);
});
return ownedArticles;
}
}

View File

@ -0,0 +1,23 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.builder.message.MessageType;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.bot.permission.PermissionNode;
@CommandMeta(aliases = "coins", permission = PermissionNode.ADMINISTRATOR, description = "Shows your current amount of StarCoins")
public class ShowCoinsCommand extends GeneralGuildCommand {
@Override
public void usage() {
}
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
event.custom(MessageType.PRIMARY, "bot.coins.coin_status", api.getBotManager().getGuildManager().getCoins(event.getGuild()))
.addLink(translate("bot.coins.buy_more", event.getLanguage()), "https://dash.sheepstar.xyz/shop")
.send();
}
}

View File

@ -0,0 +1,33 @@
package xyz.sheepstar.core.commands.general;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.PublicCommandException;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.bot.permission.PermissionNode;
@CommandMeta(aliases = "module", subAliases = "prefix", permission = PermissionNode.ADMINISTRATOR,
description = "Shows/updates a prefix from a module")
public class ShowPrefixCommand extends GeneralGuildCommand {
@Override
public void generalUsage() {
usage("newPrefix", "Changes the prefix of the module").add();
}
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
if (!moduleManager.isEnabled(event.getGuild(), moduleName))
throw new PublicCommandException("bot.module.not_enabled");
if (args.exists("newPrefix")) {
String prefix = args.getString("newPrefix");
if (prefix.length() > 5) prefix = prefix.substring(0, 5);
moduleManager.updatePrefix(event.getGuild(), moduleName.toLowerCase(), prefix);
event.success("bot.module.prefix_updated", moduleName.toLowerCase(), prefix);
} else {
event.primary("bot.module.prefix", moduleName.toLowerCase(), moduleManager.getPrefix(event.getGuild(), moduleName.toLowerCase()));
}
}
}

View File

@ -0,0 +1,57 @@
package xyz.sheepstar.core.commands.general;
import net.dv8tion.jda.api.entities.Emoji;
import net.dv8tion.jda.api.interactions.components.ButtonStyle;
import xyz.sheepstar.util.bot.builder.message.DefaultResponseBuilder;
import xyz.sheepstar.util.bot.builder.message.MessageType;
import xyz.sheepstar.util.bot.builder.message.Translate;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.PublicCommandException;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.bot.permission.PermissionNode;
import java.util.HashMap;
@CommandMeta(aliases = "language", permission = PermissionNode.ADMINISTRATOR, description = "Changes the language of the bot")
public class SwitchLanguageCommand extends GeneralGuildCommand {
private final HashMap<String, Emoji> languages = new HashMap<>();
public SwitchLanguageCommand() {
api.getBotManager().getLanguageManager().getLanguages().forEach(language ->
languages.put((String) language.get("code"), Emoji.fromUnicode((String) language.get("emoji"))));
}
@Override
public void usage() {
}
public DefaultResponseBuilder sendLanguageMessage(GuildEventController event) {
DefaultResponseBuilder builder = event.custom(MessageType.PRIMARY, "bot.language_update", "null", Translate.ONLY_TITLE);
languages.forEach((language, emoji) ->
builder.addButton(language.equals(getLanguage(event.getGuild())) ? ButtonStyle.PRIMARY : ButtonStyle.SECONDARY, language, emoji));
return builder;
}
@Override
public void execute(GuildEventController event, Arguments args, String moduleName) throws Exception {
sendLanguageMessage(event)
.withDescription(translate("bot.choose_language", event.getLanguage()))
.send();
}
@Override
public void buttonClick(GuildEventController event, String id) throws Exception {
if (!languages.containsKey(id)) throw new PublicCommandException("bot.unknown_language");
api.getBotManager().getGuildManager().updateLanguage(event.getGuild(), id);
sendLanguageMessage(event)
.withDescription(translate("bot.language_updated", event.getLanguage(),
api.getBotManager().getLanguageManager().getName(id.toLowerCase())))
.send();
}
}

View File

@ -0,0 +1,62 @@
package xyz.sheepstar.util;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.User;
import xyz.sheepstar.util.bot.command.GuildCommand;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.console.ConsoleManager;
import xyz.sheepstar.util.http.client.Requester;
import xyz.sheepstar.util.http.client.objects.ArticleObject;
import xyz.sheepstar.util.http.client.objects.GiftObject;
import xyz.sheepstar.util.http.client.objects.ShopObject;
import xyz.sheepstar.util.validation.trigger.TriggerValidator;
import java.io.File;
public interface Sheepstar {
void shutdown();
void shutdown(String message);
void shutdown(String message, int code);
String translate(String translationString, String languageCode, Object... values);
String translate(String translationString, Object... values);
void insertTranslation(String translationString, String languageCode, String translation);
boolean isOwner(User user);
boolean isSupporter(User user);
JDA getJDA();
JDA getMainJDA();
File getFromCache(String fileName);
String getModuleName(String className);
void registerListener(String moduleName, Object listener);
void registerCommand(String moduleName, GuildCommand command);
void registerGeneralCommand(GeneralGuildCommand command);
ConsoleManager getConsoleManager();
Requester getRequester();
boolean isDebugModeEnabled();
ShopObject getShop();
ArticleObject getArticles();
GiftObject getGifts();
TriggerValidator getTriggerValidator();
}

View File

@ -0,0 +1,488 @@
package xyz.sheepstar.util;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.ReadyEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction;
import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder;
import net.dv8tion.jda.api.sharding.ShardManager;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import xyz.sheepstar.util.action.ScheduledExecutorPool;
import xyz.sheepstar.util.bot.command.GuildCommand;
import xyz.sheepstar.util.bot.command.general.GeneralGuildCommand;
import xyz.sheepstar.util.bot.manager.BotManager;
import xyz.sheepstar.util.configuration.DatabaseConfiguration;
import xyz.sheepstar.util.configuration.SheepstarConfiguration;
import xyz.sheepstar.util.console.ConsoleManager;
import xyz.sheepstar.util.event.api.EventManager;
import xyz.sheepstar.util.http.client.Requester;
import xyz.sheepstar.util.http.client.objects.ArticleObject;
import xyz.sheepstar.util.http.client.objects.GiftObject;
import xyz.sheepstar.util.http.client.objects.ShopObject;
import xyz.sheepstar.util.http.client.objects.internal.ArticleObjectImpl;
import xyz.sheepstar.util.http.client.objects.internal.GiftObjectImpl;
import xyz.sheepstar.util.http.client.objects.internal.ShopObjectImpl;
import xyz.sheepstar.util.http.server.WebServer;
import xyz.sheepstar.util.internal.manager.CacheManager;
import xyz.sheepstar.util.internal.manager.ConfigurationManager;
import xyz.sheepstar.util.internal.manager.ListenerManager;
import xyz.sheepstar.util.internal.manager.OptionManager;
import xyz.sheepstar.util.log.LogManager;
import xyz.sheepstar.util.module.ModuleManager;
import xyz.sheepstar.util.sql.DatabaseCheckerThread;
import xyz.sheepstar.util.sql.SheepDatabase;
import xyz.sheepstar.util.validation.trigger.TriggerValidator;
import javax.security.auth.login.LoginException;
import java.io.File;
import java.util.Random;
public class SheepstarImpl extends ListenerAdapter implements Sheepstar {
private final Logger LOG = LogManager.getLog(SheepstarImpl.class);
private final String[] args;
private final ScheduledExecutorPool scheduledExecutorPool = new ScheduledExecutorPool();
private final TriggerValidator triggerValidator = new TriggerValidator();
private final EventManager eventManager = new EventManager(this);
private SheepDatabase database;
private ModuleManager moduleManager;
private ConfigurationManager configurationManager;
private CacheManager cacheManager;
private OptionManager optionManager;
private ListenerManager listenerManager;
private BotManager botManager;
private WebServer webServer;
private Requester requester;
private ConsoleManager consoleManager;
private ShardManager shardManager;
private int readyShards = 0;
private boolean debugModeEnabled = false;
/**
* Basic constructor of the Sheepstar instance
*
* @param args The program arguments
*/
public SheepstarImpl(String[] args) {
this.args = args;
}
/**
* Initializes sheepstar
*/
public void init() {
LOG.info("Starting Sheepstar...");
optionManager = new OptionManager(this, args);
optionManager.parseDefault();
debugModeEnabled = optionManager.hasOption("debugMode");
LOG.info("Loading configuration....");
configurationManager = new ConfigurationManager(this, new File(optionManager.getOptionValue("cf")));
LOG.info("Configuration file {} loaded successfully", optionManager.getOptionValue("cf"));
moduleManager = new ModuleManager(getConfig().getModuleDirectory(), this);
listenerManager = new ListenerManager(this);
initExecutionPools();
connectDatabase();
LOG.info("Starting the JDA instance");
setupJDA();
LOG.info("Starting the internal http webserver");
setupHttp();
LOG.info("Waiting for the JDA instance to start");
while (readyShards != shardManager.getShardsTotal()) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
}
LOG.info("Successfully started the JDA instance");
requester = new Requester(this);
botManager = new BotManager(this);
consoleManager = new ConsoleManager(this);
LOG.info("Downloading files to cache");
cacheManager = new CacheManager(this);
cacheManager.loadDefaultCacheElements();
LOG.info("Successfully downloaded all files to cache");
LOG.info("Loading modules...");
moduleManager.loadAllModules();
}
@Override
public void onReady(@NotNull ReadyEvent event) {
readyShards++;
}
/**
* Finishes up the work
*/
public void finish() {
LOG.info("Finishing up...");
String debugGuild = getConfig().getCommandConfiguration().getDebugGuild();
CommandListUpdateAction updateAction = debugGuild.isEmpty() ? getMainJDA().updateCommands()
: getMainJDA().getGuildById(debugGuild).updateCommands();
updateAction.addCommands(listenerManager.rewriteCommandsToData()).complete();
listenerManager.updateCommandMetaInternal();
LOG.info("Finished up loading");
}
/**
* Initializes the scheduled executor pool
*/
public void initExecutionPools() {
getConfig().getPools().forEach(pool -> scheduledExecutorPool.createPool(pool.getPoolName(), pool.getCorePoolSize()));
}
/**
* Shuts down the api with no reason
*/
public void shutdown() {
shutdown("No reason provided", 0);
}
/**
* Shuts down the api with a message
*
* @param message The message you want to provide
*/
public void shutdown(String message) {
shutdown(message, 0);
}
/**
* Shuts down the api with a message and a code
*
* @param message The message you want to provide
* @param code The code you want to provide
*/
public void shutdown(String message, int code) {
LOG.info("Shutting down... Reason: " + message);
try {
getJDA().shutdown();
} catch (NullPointerException ignored) {
}
System.exit(code);
}
/**
* Connects to the database with the login parameters provided in the file
*/
private void connectDatabase() {
DatabaseConfiguration config = getConfig().getDatabaseConfiguration();
database = new SheepDatabase(this, config.getHostname(), config.getUsername(), config.getPassword(), config.getDatabase());
database.connect();
if (!database.isConnected())
shutdown("Could not connect to database, please check your config.");
new DatabaseCheckerThread(this).start();
}
/**
* Initializes the JDA
*/
private void setupJDA() {
try {
shardManager = DefaultShardManagerBuilder.createDefault(getConfig().getToken())
.addEventListeners(this)
.setShardsTotal(Integer.parseInt(getOptionManager().getOptionValue("shardAmount"))).build();
} catch (LoginException e) {
shutdown("Could not create a JDA instance: " + e.getMessage());
}
}
/**
* Creates and starts the Http server
*/
private void setupHttp() {
webServer = new WebServer();
webServer.start();
}
/**
* Gets the event manager
*
* @return the event manager
*/
public EventManager getEventManager() {
return eventManager;
}
/**
* Gets the database
*
* @return the database
*/
public SheepDatabase getDatabase() {
return database;
}
/**
* Gets the module manager
*
* @return the module manager
*/
public ModuleManager getModuleManager() {
return moduleManager;
}
/**
* Gets the bot manager
*
* @return the bot manager
*/
public BotManager getBotManager() {
return botManager;
}
/**
* Gets a translation from a string
*
* @param translationString The translation code/string
* @param languageCode The language you want to get the translation from
* @param values The objects you want to add to your translation
* @return the translation
*/
public String translate(String translationString, String languageCode, Object... values) {
return getBotManager().getTranslationManager().getTranslation(translationString, languageCode, values);
}
/**
* Gets a translation from a string with the english language code
*
* @param translationString The translation code/string
* @param values The objects you want to add to your translation
* @return the translation
*/
public String translate(String translationString, Object... values) {
return translate(translationString, "en", values);
}
/**
* Creates a translation
*
* @param translationString The translation code/string
* @param languageCode The language code
* @param translation The translation itself
*/
public void insertTranslation(String translationString, String languageCode, String translation) {
getBotManager().getTranslationManager().translate(translationString, languageCode, translation);
}
/**
* Gets a random JDA instance
*
* @return the jda instance
*/
public JDA getJDA() {
return shardManager.getShards().get(new Random().nextInt(shardManager.getShardsTotal()));
}
/**
* Gets the main jda instance
*
* @return the main jda instance
*/
public JDA getMainJDA() {
return shardManager.getShards().get(0);
}
/**
* Gets the shard manager
*
* @return the shard manager
*/
public ShardManager getShardManager() {
return shardManager;
}
/**
* Gets the console manager
*
* @return the console manager
*/
public ConsoleManager getConsoleManager() {
return consoleManager;
}
/**
* Gets the http requester
*
* @return the requester
*/
public Requester getRequester() {
return requester;
}
/**
* Gets the sheepstar configuration
*
* @return the sheepstar configuration
*/
public SheepstarConfiguration getConfig() {
return configurationManager.getConfiguration();
}
/**
* Checks if the user is in the list of owners
*
* @param user The user you want to check
* @return <code>true</code> if the member is an owner of the bot, otherwise <code>false</code>
*/
public boolean isOwner(User user) {
for (String existingOwner : getConfig().getPermissionConfiguration().getBotOwner())
if (user.getId().equals(existingOwner)) return true;
return false;
}
/**
* Checks if the user has the supporter/moderator role on the sheepstar discord
*
* @param user The user you want to check
* @return <code>true</code> if the member is a supporter, otherwise <code>false</code>
*/
public boolean isSupporter(User user) {
try {
return getJDA().getGuildById(getConfig().getPermissionConfiguration().getSupporter().getGuildID()).retrieveMember(user).complete()
.getRoles().contains(getJDA().getRoleById(getConfig().getPermissionConfiguration().getSupporter().getRoleID()));
} catch (Exception e) {
return false;
}
}
/**
* Gets a file from the cache
*
* @param fileName The file you want to get
* @return the file from the cache
*/
public File getFromCache(String fileName) {
return cacheManager.getFile(fileName);
}
/**
* Downloads an asset directly to the cache
*
* @param url The url you want to get the asset from
* @param fileName The name of the file
*/
public void downloadCachedElement(String url, String fileName) {
cacheManager.downloadAsset(url, fileName);
}
/**
* Gets the option manager
*
* @return the option manager
*/
public OptionManager getOptionManager() {
return optionManager;
}
/**
* Gets the name of the module by a class name
*
* @param className The name of the class you want to get the module from
* @return the name of the module
*/
public String getModuleName(String className) {
return listenerManager.getModuleName(className);
}
/**
* Gets the listener manager
*
* @return the listener manager
*/
public ListenerManager getListenerManager() {
return listenerManager;
}
/**
* Registers a listener
*
* @param moduleName The name of the module you want to use
* @param listener The listener you want to register
*/
public void registerListener(String moduleName, Object listener) {
listenerManager.registerListener(moduleName, listener);
}
/**
* Registers a command
*
* @param moduleName The name of the module you want to use
* @param command The command you want to register
*/
public void registerCommand(String moduleName, GuildCommand command) {
listenerManager.registerCommand(moduleName, command);
}
/**
* Registers a general command
*
* @param command The general command you want to register
*/
public void registerGeneralCommand(GeneralGuildCommand command) {
listenerManager.registerGeneralCommand(command);
}
/**
* Shows you the current value of the debug mode
*
* @return <code>true</code> if the debug mode is enabled, otherwise <code>false</code>
*/
public boolean isDebugModeEnabled() {
return debugModeEnabled;
}
/**
* Gets the scheduler
*
* @return the scheduler
*/
public ScheduledExecutorPool getScheduledExecutorPool() {
return scheduledExecutorPool;
}
@Override
public ShopObject getShop() {
return new ShopObjectImpl(this);
}
@Override
public ArticleObject getArticles() {
return new ArticleObjectImpl(this);
}
@Override
public GiftObject getGifts() {
return new GiftObjectImpl(this);
}
@Override
public TriggerValidator getTriggerValidator() {
return triggerValidator;
}
}

View File

@ -0,0 +1,31 @@
package xyz.sheepstar.util.action;
import xyz.sheepstar.core.SheepstarCore;
import xyz.sheepstar.util.SheepstarImpl;
public abstract class RepeatedAction extends Thread {
protected SheepstarImpl api = SheepstarCore.getSheepstar();
/**
* The time needed to re-run the specific task (in seconds)
*
* @return the needed time
*/
public abstract long time();
/**
* Your execution logic
*/
public abstract void execute();
@Override
public void run() {
execute();
try {
Thread.sleep(time() * 1000);
} catch (InterruptedException ignored) {
}
run();
}
}

View File

@ -0,0 +1,60 @@
package xyz.sheepstar.util.action;
import java.util.HashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorPool {
private final HashMap<String, ScheduledExecutorService> executorServices = new HashMap<>();
/**
* Executes the given task directly
*
* @param pool The pool to execute the task in
* @param runnable The task to execute
* @return this class
*/
public ScheduledExecutorPool executeInstant(String pool, Runnable runnable) {
executorServices.get(pool).execute(runnable);
return this;
}
/**
* Executes the given task after the given delay
*
* @param pool The pool to execute the task in
* @param runnable The task to execute
* @param delay The delay
* @param timeUnit The time unit of the delay
* @return this class
*/
public ScheduledExecutorPool executeAfter(String pool, Runnable runnable, long delay, TimeUnit timeUnit) {
executorServices.get(pool).schedule(runnable, delay, timeUnit);
return this;
}
/**
* Shuts down the given pool
*
* @param poolName The name of the pool to shut down
* @return this class
*/
public ScheduledExecutorPool shutdownPool(String poolName) {
executorServices.get(poolName).shutdown();
return this;
}
/**
* Creates a new pool with the given name
*
* @param poolName The name of the pool
* @param corePoolSize The core pool size
* @return this class
*/
public ScheduledExecutorPool createPool(String poolName, int corePoolSize) {
executorServices.put(poolName, Executors.newScheduledThreadPool(corePoolSize));
return this;
}
}

View File

@ -0,0 +1,68 @@
package xyz.sheepstar.util.bot.builder.message;
import java.util.ArrayList;
import java.util.Arrays;
public class BeautifulDescriptionBuilder {
public ArrayList<MessageField> fields;
/**
* Constructor of the {@link BeautifulDescriptionBuilder}
*
* @param fields The fields you want to add as default
*/
public BeautifulDescriptionBuilder(ArrayList<MessageField> fields) {
this.fields = fields;
}
/**
* Constructor of the {@link BeautifulDescriptionBuilder}
*
* @param fields The fields you want to add as default
*/
public BeautifulDescriptionBuilder(MessageField... fields) {
this.fields = new ArrayList<>(Arrays.asList(fields));
}
/**
* Constructor of the {@link BeautifulDescriptionBuilder} without any fields
*/
public BeautifulDescriptionBuilder() {
this.fields = new ArrayList<>();
}
/**
* Adds a new field to the list
*
* @param field The field you want to add
*/
public void addField(MessageField field) {
fields.add(field);
}
/**
* Builds the message
*
* @return the built message
*/
public String buildDefault() {
StringBuilder fieldBuilder = new StringBuilder();
for (MessageField field : fields) {
fieldBuilder.append("**").append(field.getTitle()).append("**").append("\n");
for (String subField : field.getSubFields())
fieldBuilder.append("> ").append(subField).append("\n");
fieldBuilder.append("\n");
}
return fieldBuilder.toString();
}
/**
* Gets all fields of the builder
*
* @return all fields
*/
public ArrayList<MessageField> getFields() {
return fields;
}
}

View File

@ -0,0 +1,261 @@
package xyz.sheepstar.util.bot.builder.message;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.time.temporal.TemporalAccessor;
import java.util.ArrayList;
public class DefaultEmbedBuilder extends EmbedBuilder {
private ArrayList<MessageField> fields = new ArrayList<>();
/**
* Constructor of the {@link DefaultEmbedBuilder}
*
* @param type The color of the message
*/
public DefaultEmbedBuilder(MessageType type) {
setColor(type.getColor());
}
/**
* Constructor of the {@link DefaultEmbedBuilder}
*/
public DefaultEmbedBuilder() {
}
/**
* Sets the author of the embed
*
* @param name The name of the author
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder setAuthor(@Nullable String name) {
super.setAuthor(name);
return this;
}
/**
* Sets the author of the embed
*
* @param name The name of the author
* @param url The url of the title
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder setAuthor(@Nullable String name, @Nullable String url) {
super.setAuthor(name, url);
return this;
}
/**
* Sets the author of the embed
*
* @param name The name of the author
* @param url The url of the title
* @param iconUrl The url of the icon
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder setAuthor(@Nullable String name, @Nullable String url, @Nullable String iconUrl) {
super.setAuthor(name, url, iconUrl);
return this;
}
/**
* Sets the color of the embed
*
* @param color The new color
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder setColor(@Nullable Color color) {
super.setColor(color);
return this;
}
/**
* Sets the footer of the embed
*
* @param text The text of the footer
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder setFooter(@Nullable String text) {
super.setFooter(text);
return this;
}
/**
* Sets the footer of the embed
*
* @param text The text of the footer
* @param iconUrl The url of the icon
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder setFooter(@Nullable String text, @Nullable String iconUrl) {
super.setFooter(text, iconUrl);
return this;
}
/**
* Sets the image of the embed
*
* @param url The url of the image
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder setImage(@Nullable String url) {
super.setImage(url);
return this;
}
/**
* Sets the thumbnail of the embed
*
* @param url The url of the thumbnail
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder setThumbnail(@Nullable String url) {
super.setThumbnail(url);
return this;
}
/**
* Sets the timestamp of the embed
*
* @param temporal The timezone in the footer
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder setTimestamp(@Nullable TemporalAccessor temporal) {
super.setTimestamp(temporal);
return this;
}
/**
* Sets the title of the embed
*
* @param title The new title of the embed
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder setTitle(@Nullable String title) {
super.setTitle(title);
return this;
}
/**
* Sets the title of the embed
*
* @param title The new title of the embed
* @param url The url of the title
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder setTitle(@Nullable String title, @Nullable String url) {
super.setTitle(title, url);
return this;
}
/**
* Adds a new blank field to the field
*
* @param inline Is the field inline?
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder addBlankField(boolean inline) {
super.addBlankField(inline);
return this;
}
/**
* Adds a new field to the embed
*
* @param name The name of the field
* @param value The value of the field
* @param inline Is the field inline?
* @return the current {@link DefaultEmbedBuilder} instance
*/
@Override
public DefaultEmbedBuilder addField(@Nullable String name, @Nullable String value, boolean inline) {
super.addField(name, value, inline);
return this;
}
/**
* Adds a new beautiful field
*
* @param field The field you want to add
* @return the current {@link DefaultEmbedBuilder} instance
*/
public DefaultEmbedBuilder addBField(MessageField field) {
fields.add(field);
return this;
}
/**
* Adds a new beautiful field
*
* @param title The title of the field
* @param emote The emote of the field
* @param subFields All subfields you want to add
* @return the current {@link DefaultEmbedBuilder} instance
*/
public DefaultEmbedBuilder addBField(String title, FieldEmote emote, String... subFields) {
fields.add(new MessageField(title, emote, subFields));
return this;
}
/**
* Adds a new beautiful field
*
* @param title The title of the field
* @param subFields All subfields you want to add
* @return the current {@link DefaultEmbedBuilder} instance
*/
public DefaultEmbedBuilder addBField(String title, String... subFields) {
fields.add(new MessageField(title, subFields));
return this;
}
/**
* Sets all fields of the embed
*
* @param fields The new fields
* @return the current {@link DefaultEmbedBuilder} instance
*/
public DefaultEmbedBuilder setFields(ArrayList<MessageField> fields) {
this.fields = fields;
return this;
}
/**
* Builds the message to an embed
*
* @return the message as an embed
*/
public MessageEmbed toEmbed() {
return this.setDescription(getDescriptionBuilder() + new BeautifulDescriptionBuilder(fields).buildDefault()).build();
}
/**
* Builds the message to an {@link Message} object
*
* @return the message as an {@link Message} object
*/
public Message toMessage() {
return new MessageBuilder().setEmbed(toEmbed()).build();
}
}

View File

@ -0,0 +1,334 @@
package xyz.sheepstar.util.bot.builder.message;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.Button;
import net.dv8tion.jda.api.interactions.components.ButtonStyle;
import xyz.sheepstar.core.SheepstarCore;
import xyz.sheepstar.util.bot.command.GuildEventController;
import java.util.ArrayList;
public class DefaultResponseBuilder {
private final GuildEventController eventController;
private final Class<?> trigger;
private final ArrayList<Button> buttons = new ArrayList<>();
private ArrayList<MessageField> fields = new ArrayList<>();
private MessageType messageType = MessageType.PRIMARY;
private String title;
private String description;
private boolean isEphemeral = false;
/**
* Constructor of the {@link DefaultResponseBuilder}
*
* @param eventController The {@link GuildEventController} from the listener
* @param trigger The button trigger
*/
public DefaultResponseBuilder(GuildEventController eventController, Class<?> trigger) {
this.eventController = eventController;
this.trigger = trigger;
}
/**
* Creates the {@link DefaultResponseBuilder} with only the text channel
* <p>
* <b>Warning: This could end up in errors because some methods need the user in order to run</b>
*
* @param channel The channel in which the message should be sent
* @param buttonTrigger The trigger of the buttons
* Only needed when you want to use buttons. If not, set it to <b>null</b>
* @return the created {@link DefaultResponseBuilder}
*/
public static DefaultResponseBuilder createSimple(TextChannel channel, Class<?> buttonTrigger) {
return new DefaultResponseBuilder(new GuildEventController(null, null, channel, channel.getGuild(), buttonTrigger), buttonTrigger);
}
/**
* Creates the {@link DefaultResponseBuilder} with only the text channel
* <p>
* <b>Warning: This could end up in errors since a channel is needed for sending the message</b>
*
* @param guild The guild you want to use
* @param buttonTrigger The trigger of the buttons
* Only needed when you want to use buttons. If not, set it to <b>null</b>
* @return the created {@link DefaultResponseBuilder}
*/
public static DefaultResponseBuilder createSimple(Guild guild, Class<?> buttonTrigger) {
return new DefaultResponseBuilder(new GuildEventController(null, null, null, guild, buttonTrigger), buttonTrigger);
}
/**
* Creates the {@link DefaultResponseBuilder} with all needed values
*
* @param member The member that sent the message
* @param channel The channel in which you want to send the message
* @param buttonTrigger The trigger of the buttons
* Only needed when you want to use buttons. If not, set it to <b>null</b>
* @return the created {@link DefaultResponseBuilder}
*/
public static DefaultResponseBuilder createFrom(Member member, TextChannel channel, Class<?> buttonTrigger) {
return new DefaultResponseBuilder(new GuildEventController(member.getUser(), member, channel, channel.getGuild(), buttonTrigger), buttonTrigger);
}
/**
* Creates the {@link DefaultResponseBuilder} by the {@link SlashCommandEvent}
*
* @param event The event provided from the listener
* @param buttonTrigger The trigger of the buttons
* Only needed when you want to use buttons. If not, set it to <b>null</b>
* @return the created {@link DefaultResponseBuilder}
*/
public static DefaultResponseBuilder createFrom(SlashCommandEvent event, Class<?> buttonTrigger) {
return new DefaultResponseBuilder(new GuildEventController(event.getUser(),
event.getMember(), event.getTextChannel(), event.getGuild(), buttonTrigger), buttonTrigger);
}
/**
* Creates the {@link DefaultResponseBuilder} by the {@link GuildMessageReceivedEvent}
*
* @param event The event provided from the listener
* @param buttonTrigger The trigger of the buttons
* Only needed when you want to use buttons. If not, set it to <b>null</b>
* @return the created {@link DefaultResponseBuilder}
*/
public static DefaultResponseBuilder createFrom(GuildMessageReceivedEvent event, Class<?> buttonTrigger) {
return new DefaultResponseBuilder(new GuildEventController(event.getAuthor(),
event.getMember(), event.getChannel(), event.getGuild(), buttonTrigger), buttonTrigger);
}
/**
* Sets the color of the response
*
* @param messageType The new message color
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder withColor(MessageType messageType) {
this.messageType = messageType;
return this;
}
/**
* Sets the title of the response
*
* @param title The new message title
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder withTitle(String title) {
this.title = title;
return this;
}
/**
* Sets the description of the response
*
* @param description The new message description
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder withDescription(String description) {
this.description = description;
return this;
}
/**
* Sets all fields of the response
*
* @param fields The new field array
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder withFields(ArrayList<MessageField> fields) {
this.fields = fields;
return this;
}
/**
* Makes the message ephemeral (only visible to the sender)
*
* @param isEphemeral Should the response be ephemeral?
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder isEphemeral(boolean isEphemeral) {
this.isEphemeral = isEphemeral;
return this;
}
/**
* Adds a new field to the response
*
* @param title The title of the message field
* @param subFields All subfields of the message field as an array
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder addField(String title, ArrayList<String> subFields) {
fields.add(new MessageField(title, subFields.toArray(new String[0])));
return this;
}
/**
* Adds a new field to the response with an emote
*
* @param title The title of the message field
* @param emote The emote of the message field
* @param subFields All subfields of the message field
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder addField(String title, FieldEmote emote, String... subFields) {
fields.add(new MessageField(title, emote, subFields));
return this;
}
/**
* Adds a new field to the response
*
* @param title The title of the message field
* @param subFields All subfields of the message field
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder addField(String title, String... subFields) {
fields.add(new MessageField(title, subFields));
return this;
}
/**
* Adds a button to the response
*
* @param style The style of the button you want to add
* @param id The id of the button to use it in events later
* @param text The text the button should display
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder addButton(ButtonStyle style, String id, String text) {
buttons.add(Button.of(style, trigger.getName() + "~" + id, text));
return this;
}
/**
* Adds a button to the response
*
* @param style The style of the button you want to add
* @param id The id of the button to use it in events later
* @param emoji The emoji the button should display
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder addButton(ButtonStyle style, String id, Emoji emoji) {
buttons.add(Button.of(style, trigger.getName() + "~" + id, emoji));
return this;
}
/**
* Adds a button to the response
*
* @param style The style of the button you want to add
* @param id The id of the button to use it in events later
* @param text The text the button should display
* @param emoji The emoji the button should display
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder addButton(ButtonStyle style, String id, String text, Emoji emoji) {
buttons.add(Button.of(style, trigger.getName() + "~" + id, text, emoji));
return this;
}
/**
* Adds a link button to the response
*
* @param text The text the button should display
* @param link The link of the button
* @return the current {@link DefaultResponseBuilder} instance
*/
public DefaultResponseBuilder addLink(String text, String link) {
buttons.add(Button.of(ButtonStyle.LINK, link, text));
return this;
}
/**
* Builds the response to the message
*
* @return the built message
*/
public Message build() {
MessageBuilder builder = new MessageBuilder();
// TODO: Let the user decide what he likes
// Currently, only embeds are available
EmbedBuilder embed = new EmbedBuilder();
embed.setTitle(title);
if (description != null) {
StringBuilder descriptionBuilder = new StringBuilder();
for (String s : description.split("\n"))
descriptionBuilder.append("> ").append(s).append("\n");
embed.setDescription(descriptionBuilder);
}
embed.setColor(messageType.getColor());
// Add all fields
if (!fields.isEmpty())
embed.setDescription(description != null ? description : "" + new BeautifulDescriptionBuilder(fields).buildDefault());
// Set the action rows (buttons)
if (!buttons.isEmpty())
builder.setActionRows(ActionRow.of(buttons));
// Set the author footer
if (eventController.getAuthor() != null)
embed.setFooter(SheepstarCore.getSheepstar().translate("bot.requested_by", eventController.getLanguage(),
eventController.getAuthor().getName()), eventController.getAuthor().getAvatarUrl());
// Only set errors ephemeral
if (messageType == MessageType.ERROR)
isEphemeral = true;
return builder.setEmbed(embed.build()).build();
}
/**
* Sends the message to the guild / replies
*/
public void send() {
eventController.reply(this);
}
/**
* Gets all buttons of the builder
*
* @return all buttons
*/
public ArrayList<Button> getButtons() {
return buttons;
}
/**
* Gets the fields of the builder
*
* @return all message fields
*/
public ArrayList<MessageField> getFields() {
return fields;
}
/**
* Gets the type of the message
*
* @return the message type
*/
public MessageType getMessageType() {
return messageType;
}
/**
* Is the message ephemeral (only visible to the sender)
*
* @return <code>true</code> if the message is ephemeral, otherwise <code>false</code>
*/
public boolean isEphemeral() {
return isEphemeral;
}
}

View File

@ -0,0 +1,30 @@
package xyz.sheepstar.util.bot.builder.message;
public enum FieldEmote {
/**
* The "information" emote
*/
INFO,
/**
* Sets no emote as default
*/
NOTHING,
/**
* The "successful" emote
*/
SUCCESS,
/**
* The emote that shows up when an error happened
*/
ERROR,
/**
* The emote that shows up when you w
*/
WARNING
}

View File

@ -0,0 +1,87 @@
package xyz.sheepstar.util.bot.builder.message;
public class MessageField {
private String title;
private String[] subFields;
private FieldEmote emote = FieldEmote.NOTHING;
/**
* Constructor of the {@link MessageField}
*
* @param title The title of the field
* @param emote The emote which stands next to the title
* <i>This is optional</i>
* @param subFields All fields below the title
*/
public MessageField(String title, FieldEmote emote, String... subFields) {
this.title = title;
this.subFields = subFields;
this.emote = emote;
}
/**
* Constructor of the {@link MessageField} without the emote parameter
*
* @param title The title of the field
* @param subFields All fields below the title
*/
public MessageField(String title, String... subFields) {
this.title = title;
this.subFields = subFields;
}
/**
* Gets the title of the field
*
* @return the title of the field
*/
public String getTitle() {
return title;
}
/**
* Sets the title of the field
*
* @param title The new title
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Gets all subfields of the message field
*
* @return all subfields
*/
public String[] getSubFields() {
return subFields;
}
/**
* Sets all subfields of the message field
*
* @param subFields All new subfields
*/
public void setSubFields(String[] subFields) {
this.subFields = subFields;
}
/**
* Gets the emote next to the message field
*
* @return the emote of the field
*/
public FieldEmote getEmote() {
return emote;
}
/**
* Sets the emote next to the field
*
* @param emote The new field emote
*/
public void setEmote(FieldEmote emote) {
this.emote = emote;
}
}

View File

@ -0,0 +1,34 @@
package xyz.sheepstar.util.bot.builder.message;
import java.awt.*;
public enum MessageType {
ERROR(new Color(0xde1f1f)),
PRIMARY(new Color(0x748AD6)),
SUCCESS(new Color(0x2ecc71)),
WARNING(new Color(0xFF8C00)),
SECONDARY(new Color(0x4E4C4C)),
WHITE(new Color(0xE9E3E3)),
BLACK(new Color(0x222222));
private final Color color;
/**
* Constructor of the {@link MessageType} enum
*
* @param color The color of the message
*/
MessageType(Color color) {
this.color = color;
}
/**
* Gets the color of the message type
*
* @return the color as {@link Color}
*/
public Color getColor() {
return color;
}
}

View File

@ -0,0 +1,25 @@
package xyz.sheepstar.util.bot.builder.message;
public enum Translate {
/**
* Only translates the title of the message
*/
ONLY_TITLE,
/**
* Only translates the description of the message
*/
ONLY_DESCRIPTION,
/**
* Translates the title & the description
*/
BOTH,
/**
* Translates nothing, neither the title nor the description
*/
NOTHING
}

View File

@ -0,0 +1,116 @@
package xyz.sheepstar.util.bot.command;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.GuildChannel;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.User;
import xyz.sheepstar.core.SheepstarCore;
import java.util.HashMap;
public class Arguments {
private final HashMap<String, String> argumentList;
private final JDA jda = SheepstarCore.getSheepstar().getJDA();
/**
* Basic constructor of the {@link Arguments} (the argument list of the {@link GuildCommand})
*
* @param argumentList The list of arguments you want to add to the command
*/
public Arguments(HashMap<String, String> argumentList) {
this.argumentList = argumentList;
}
/**
* Gets a string from the argument list
*
* @param key The key of the string you want to get
* @return the string from the argument list
*/
public String getString(String key) {
return argumentList.get(key.toLowerCase());
}
/**
* Gets an integer from the argument list
*
* @param key The key of the integer you want to get
* @return the integer from the argument list
*/
public int getInteger(String key) {
return Integer.parseInt(argumentList.get(key.toLowerCase()));
}
/**
* Gets a boolean from the argument list
*
* @param key The key of the boolean you want to get
* @return the boolean from the argument list
*/
public boolean getBoolean(String key) {
return Boolean.parseBoolean(argumentList.get(key.toLowerCase()));
}
/**
* Retrieves a user from the argument list
*
* @param key The key of the user you want to get
* @return the user from the argument list
*/
public User retrieveUser(String key) {
return jda.retrieveUserById(argumentList.get(key.toLowerCase())).complete();
}
/**
* Gets a user from the argument list
*
* @param key The key of the user you want to get
* @return the user from the argument list
*/
public User getUser(String key) {
return jda.getUserById(argumentList.get(key.toLowerCase()));
}
/**
* Gets a channel from the argument list
*
* @param key The key of the channel you want to get
* @return the channel from the argument list
*/
public GuildChannel getChannel(String key) {
return jda.getGuildChannelById(argumentList.get(key.toLowerCase()));
}
/**
* Gets a role from the argument list
*
* @param key The key of the role you want to get
* @return the role from the argument list
*/
public Role getRole(String key) {
return jda.getRoleById(argumentList.get(key.toLowerCase()));
}
/**
* Checks if the provided key exists in the argument list
*
* @param key The key you want to check
* @return <code>true</code> if the key exists, otherwise <code>false</code>
*/
public boolean exists(String key) {
return argumentList.containsKey(key.toLowerCase()) && argumentList.get(key.toLowerCase()) != null
&& !argumentList.get(key.toLowerCase()).isEmpty();
}
/**
* Gets the full list of arguments
*
* @return the full list of arguments
*/
public HashMap<String, String> getArgumentList() {
return argumentList;
}
}

View File

@ -0,0 +1,7 @@
package xyz.sheepstar.util.bot.command;
public interface CommandRunnable {
void run() throws Exception;
}

View File

@ -0,0 +1,367 @@
package xyz.sheepstar.util.bot.command;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.events.interaction.ButtonClickEvent;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.components.ButtonStyle;
import org.jetbrains.annotations.NotNull;
import xyz.sheepstar.util.bot.builder.message.MessageType;
import xyz.sheepstar.util.bot.builder.message.Translate;
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
import xyz.sheepstar.util.bot.listener.ListenerBasics;
import xyz.sheepstar.util.bot.manager.sql.SettingsManager;
import xyz.sheepstar.util.bot.permission.PermissionNode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public abstract class GuildCommand extends ListenerBasics {
protected final CommandMeta commandMeta = this.getClass().getAnnotation(CommandMeta.class);
private final ArrayList<OptionData> syntaxElements = new ArrayList<>();
private final SettingsManager settingsManager = api.getBotManager().getSettingsManager();
protected ArrayList<String> subAliases = new ArrayList<>();
protected ArrayList<String> aliases = new ArrayList<>();
/**
* The basic constructor of the {@link GuildCommand}
*/
public GuildCommand() {
addAliases();
usage();
}
/**
* Gets the full message in parts (splits with spaces and quotation marks)
*
* @param input The message input
* @return the full message in parts
*/
public static ArrayList<String> getPartsFromInput(String input) {
Matcher argumentMatcher = Pattern.compile("([^\"]\\S*|\".+?\")\\s*").matcher(input);
ArrayList<String> arguments = new ArrayList<>();
while (argumentMatcher.find()) {
arguments.add(argumentMatcher.group(1));
}
return arguments;
}
/**
* Adds all sub-aliases and aliases
*/
protected void addAliases() {
Collections.addAll(aliases, commandMeta.aliases());
Collections.addAll(subAliases, commandMeta.subAliases());
}
public void usage() {
}
public abstract void execute(GuildEventController event, Arguments args) throws Exception;
/**
* The override of the {@link SlashCommandEvent}. Used to run the execute-method
*
* @param event The {@link SlashCommandEvent} from the JDA
*/
@Override
public void onSlashCommand(@NotNull SlashCommandEvent event) {
api.getScheduledExecutorPool().executeInstant("SR-PreparePool", () -> {
if (!event.getChannelType().isGuild()) return;
if (event.getUser().isBot()) return;
if (!api.getConfig().getCommandConfiguration().isSlashEnabled()) return;
if (!aliases.contains(event.getName())) return;
if (commandMeta.subAliases().length != 0) {
if (!subAliases.contains(event.getSubcommandName())) return;
}
GuildEventController controller = new GuildEventController(event.getUser(), event.getMember(), event.getTextChannel(), event.getGuild(), this.getClass())
.useEvent(event);
if (!isEnabled(event.getGuild())) {
controller.custom(MessageType.ERROR, "bot.error", "bot.module.not_enabled", Translate.BOTH)
.addButton(ButtonStyle.SUCCESS, "enable", translate("bot.enable_module", event.getGuild()))
.send();
return;
}
HashMap<String, String> argumentMap = new HashMap<>();
event.getOptions().forEach(option -> argumentMap.put(option.getName(), option.getAsString()));
api.getScheduledExecutorPool().executeInstant("SR-CommandPool", () ->
runSecure(controller, () -> prepareExecute(controller, new Arguments(argumentMap))));
});
}
/**
* The override of the {@link GuildMessageReceivedEvent}. Used to run the execute-method
*
* @param event The {@link GuildMessageReceivedEvent} from the JDA
*/
@Override
public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) {
api.getScheduledExecutorPool().executeInstant("SR-PreparePool", () -> {
if (event.getMessage().getAuthor().isBot()) return;
String prefix = getPrefix(event.getGuild());
String messageInput = event.getMessage().getContentRaw()
.replaceAll("<@!?(\\d+)>", "$1")
.replaceAll("<@&(\\d+)>", "$1")
.replaceAll("<#(\\d+)>", "$1")
.replaceAll("\"", "");
if (!isEnabled(event.getGuild())) return;
ArrayList<String> parts = getPartsFromInput(messageInput);
if (!parts.get(0).startsWith(jda.getSelfUser().getId())) {
if (!api.getConfig().getCommandConfiguration().isPrefixEnabled()) return;
if (!event.getMessage().getContentRaw().startsWith(prefix)) return;
if (!aliases.contains(parts.get(0).substring(prefix.length()).toLowerCase())) return;
if (commandMeta.subAliases().length != 0 && !subAliases.contains(parts.get(1))) return;
} else {
if (!api.getConfig().getCommandConfiguration().isPingEnabled()) return;
if (!aliases.contains(parts.get(1))) return;
if (commandMeta.subAliases().length != 0 && !subAliases.contains(parts.get(2))) return;
}
GuildEventController controller = new GuildEventController(event.getAuthor(), event.getMember(), event.getChannel(), event.getGuild(), this.getClass())
.useEvent(event);
api.getScheduledExecutorPool().executeInstant("SR-CommandPool", () ->
runSecure(controller, () -> prepareExecute(controller, getArgumentsFromInput(parts))));
});
}
/**
* Gets the arguments from the input
*
* @param arguments The arguments you got from your message
* @return the arguments from the input
*/
public Arguments getArgumentsFromInput(ArrayList<String> arguments) throws PublicCommandException {
if (arguments.get(0).equals(jda.getSelfUser().getId())) arguments.remove(0);
arguments.remove(0);
if (commandMeta.subAliases().length != 0) arguments.remove(0);
HashMap<String, String> syntaxMap = new HashMap<>();
for (int i = 0; i < getSyntaxElements().size(); i++) {
OptionData syntaxElement = syntaxElements.get(i);
boolean argumentProvided = arguments.size() > i;
if (syntaxElement.isRequired() && !argumentProvided) {
throw new PublicCommandException("bot.wrong_syntax", parseSyntaxAsString());
}
if (argumentProvided && !isValidArgument(syntaxElement.getType(), arguments.get(i))) {
throw new PublicCommandException("bot.wrong_type", syntaxElement.getName(), syntaxElement.getType().toString());
}
syntaxMap.put(syntaxElement.getName(), argumentProvided ? arguments.get(i) : null);
}
return new Arguments(syntaxMap);
}
/**
* Gets the usage of the command as a string
*
* @return the usage of the command as a string
*/
public String parseSyntaxAsString() {
StringBuilder syntax = new StringBuilder();
for (OptionData syntaxElement : getSyntaxElements()) {
String format = syntaxElement.isRequired() ? "<%s>" : "[%s]";
if (!syntax.toString().isEmpty()) syntax.append(" ");
syntax.append(String.format(format, syntaxElement.getName()));
}
return syntax.toString();
}
/**
* Checks if the provided argument equals the provided type
*
* @param expectedType The type you want to check
* @param givenArgument The argument you want to check
* @return <code>true</code> if the argument matches the expected type, otherwise <code>false</code>
*/
public boolean isValidArgument(OptionType expectedType, String givenArgument) {
try {
if (expectedType == OptionType.INTEGER)
Integer.parseInt(givenArgument);
if (expectedType == OptionType.BOOLEAN && !(givenArgument.equals("false") || givenArgument.equals("true")))
throw new Exception();
if (expectedType == OptionType.USER && jda.retrieveUserById(givenArgument).complete() == null)
throw new Exception();
if (expectedType == OptionType.CHANNEL && jda.getGuildChannelById(givenArgument) == null)
throw new Exception();
if (expectedType == OptionType.ROLE && jda.getRoleById(givenArgument) == null)
throw new Exception();
} catch (Exception e) {
return false;
}
return true;
}
/**
* Prepares the execution of the command event
*
* @param event The {@link GuildEventController} from the events
* @param arguments The arguments from the message/event
*/
protected void prepareExecute(GuildEventController event, Arguments arguments) throws Exception {
// Check if the user has the permission to execute the command
if (!isAuthorized(event))
throw new PublicCommandException("bot.lacking_permission", commandMeta.permission().name());
// Checks if the required setting is set
if (!commandMeta.requiredSetting().isEmpty()
&& !settingsManager.getSetting(event.getGuild(), getModule(), commandMeta.requiredSetting()).equals(commandMeta.requiredSettingValue()))
throw new PublicCommandException("bot.invalid_setting", commandMeta.requiredSetting(), commandMeta.requiredSettingValue());
execute(event, arguments);
}
/**
* Checks if the user is allowed to run the command
*
* @param event The {@link GuildEventController}
* @return <code>true</code> if the user is authorized, otherwise <code>false</code>
*/
public boolean isAuthorized(GuildEventController event) {
if (commandMeta.permission() == null || commandMeta.permission() == PermissionNode.DEFAULT) return true;
if (commandMeta.permission() == PermissionNode.ADMINISTRATOR)
return event.getMember().hasPermission(Permission.ADMINISTRATOR);
if (commandMeta.permission() == PermissionNode.SERVER_OWNER)
return event.getMember().isOwner();
if (commandMeta.permission() == PermissionNode.BOT_OWNER)
if (api.isOwner(event.getAuthor())) return true;
if (commandMeta.permission() == PermissionNode.SUPPORTER)
return api.isSupporter(event.getAuthor());
return false;
}
@Override
public void onButtonClick(@NotNull ButtonClickEvent event) {
GuildEventController controller = new GuildEventController(event.getUser(), event.getMember(), event.getTextChannel(), event.getGuild(), this.getClass())
.useEvent(event);
runSecure(controller, () -> {
if (!event.getMessage().getAuthor().getId().equals(jda.getSelfUser().getId())) return;
String[] buttonMeta = event.getComponentId().split("~");
if (!buttonMeta[0].equals(getClass().getName())) return;
if (buttonMeta[1].equals("enable") && event.getMember().hasPermission(Permission.ADMINISTRATOR)) {
String moduleId = getModuleByClass(getClass());
if (api.getModuleManager().getActivated_modules().containsKey(moduleId))
moduleManager.enableModule(event.getGuild(), moduleId, "!");
controller.success("bot.module_enabled", moduleId, "!");
return;
}
if (!isEnabled(event.getGuild())) return;
if (!isAuthorized(controller)) return;
buttonClick(controller, buttonMeta[1]);
});
}
public void buttonClick(GuildEventController event, String id) throws Exception {
}
/**
* The default method to get the {@link SyntaxBuilder}
*
* @param type The option type of the syntax element
* @param name The name of the syntax element
* @param description The description of the syntax element
* @param isRequired <code>true</code> if the syntax element is required, otherwise <code>false</code>
* @return the {@link SyntaxBuilder}
*/
public SyntaxBuilder usage(OptionType type, String name, String description, boolean isRequired) {
return new SyntaxBuilder(this, type, name, description).required(isRequired);
}
/**
* Gets the {@link SyntaxBuilder}
*
* @param type The option of the syntax element
* @param name The name of the syntax element
* @param description The description of the syntax element
* @return the {@link SyntaxBuilder}
*/
public SyntaxBuilder usage(OptionType type, String name, String description) {
return new SyntaxBuilder(this, type, name, description);
}
/**
* Gets the {@link SyntaxBuilder}
*
* @param name The name of the syntax element
* @param description The description of the syntax element
* @return the created {@link SyntaxBuilder} with prefilled values
*/
public SyntaxBuilder usage(String name, String description) {
return new SyntaxBuilder(this, OptionType.STRING, name, description);
}
/**
* Adds a syntax element ({@link OptionData}) to the syntax element list
*
* @param optionData The {@link OptionData} generated by the {@link SyntaxBuilder}
*/
public void addSyntaxElement(OptionData optionData) {
syntaxElements.add(optionData);
}
/**
* Gets the list of syntax elements
*
* @return the list of syntax elements
*/
public ArrayList<OptionData> getSyntaxElements() {
return syntaxElements;
}
}

View File

@ -0,0 +1,395 @@
package xyz.sheepstar.util.bot.command;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.Event;
import net.dv8tion.jda.api.events.interaction.ButtonClickEvent;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.interactions.InteractionHook;
import xyz.sheepstar.core.SheepstarCore;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.bot.builder.message.DefaultResponseBuilder;
import xyz.sheepstar.util.bot.builder.message.MessageField;
import xyz.sheepstar.util.bot.builder.message.MessageType;
import xyz.sheepstar.util.bot.builder.message.Translate;
import java.util.ArrayList;
public class GuildEventController {
private final SheepstarImpl api = SheepstarCore.getSheepstar();
private final User author;
private final Member member;
private final TextChannel channel;
private final Guild guild;
private final Class<?> trigger;
private String translationLanguage;
private InteractionHook interactionHook;
private Event event;
/**
* Basic constructor of the {@link GuildEventController}
*
* @param author The author that triggered command event
* @param member The member that triggered the command event
* @param channel The channel of the triggered command event
* @param guild The guild of the triggered command event
* @param trigger The trigger of the command event
*/
public GuildEventController(User author, Member member, TextChannel channel, Guild guild, Class<?> trigger) {
this.author = author;
this.member = member;
this.channel = channel;
this.guild = guild;
this.trigger = trigger;
}
/**
* Waits for the user to send a message
*
* @param ephemeral Should the message be ephemeral?
*/
public void pleaseWait(boolean ephemeral) {
if (event instanceof SlashCommandEvent)
this.interactionHook = ((SlashCommandEvent) event).deferReply(ephemeral).complete();
}
/**
* Waits for the user to send a message
*/
public void pleaseWait() {
pleaseWait(false);
}
/**
* Tells the event controller to use the defined event.
* <p>
* The current supported events:
* <ol>
* <li>The {@link GuildMessageReceivedEvent}</li>
* <li>The {@link SlashCommandEvent}</li>
* <li>The {@link ButtonClickEvent}</li>
* </ol>
*
* @param event The event from the listener
* @return this class
*/
public GuildEventController useEvent(Event event) {
this.event = event;
return this;
}
/**
* Gets the author of the command event
*
* @return the author of the command event
*/
public User getAuthor() {
return author;
}
/**
* Gets the member of the command event
*
* @return the member of the command event
*/
public Member getMember() {
return member;
}
/**
* Gets the channel of the command event
*
* @return the channel of the command event
*/
public TextChannel getChannel() {
return channel;
}
/**
* Gets the guild of the command event
*
* @return the guild of the command event
*/
public Guild getGuild() {
return guild;
}
/**
* Sends an embed message to the specified channel
*
* @param message The embed message you want to send
* @param ephemeral Should only the executor see the message embed?
* Only works for the {@link SlashCommandEvent}
*/
public void reply(MessageEmbed message, boolean ephemeral) {
reply(new MessageBuilder().setEmbeds(message).build(), ephemeral);
}
/**
* Sends a message to the specified channel
*
* @param message The message you want to send
* @param ephemeral Should only the executor see the message?
* Only works for the {@link SlashCommandEvent}
*/
public void reply(Message message, boolean ephemeral) {
if (interactionHook != null) {
interactionHook.setEphemeral(ephemeral).editOriginal(message).queue(msg -> {
}, thr -> handleReplyError(message));
} else if (event instanceof GuildMessageReceivedEvent) {
((GuildMessageReceivedEvent) event).getMessage().reply(message).queue(msg -> {
}, thr -> handleReplyError(message));
} else if (event instanceof SlashCommandEvent) {
((SlashCommandEvent) event).reply(message).setEphemeral(ephemeral).queue(msg -> {
}, thr -> handleReplyError(message));
} else if (event instanceof ButtonClickEvent) {
((ButtonClickEvent) event).editMessage(message).queue(msg -> {
}, thr -> handleReplyError(message));
} else {
channel.sendMessage(message).queue(msg -> {
}, thr -> {
});
}
}
/**
* Sends a message to the specified channel (on error)
*
* @param msg The message you want to send
*/
private void handleReplyError(Message msg) {
channel.sendMessage(new MessageBuilder(msg).append("\n*:warning: Could not reply to message, sending here*").build()).queue(m -> {
}, thr -> {
});
}
/**
* Sends a message to the specified channel
*
* @param message The message you want to send
*/
public void reply(DefaultResponseBuilder message) {
Message build = message.build();
reply(build, message.isEphemeral());
}
/**
* Sends a message to the specified channel
*
* @param message The message you want to send
*/
public void reply(Message message) {
reply(message, false);
}
/**
* Sends an embed message to the specified channel
*
* @param embed The embed message you want to send
*/
public void reply(MessageEmbed embed) {
reply(embed, true);
}
/**
* Sends a simple message to the specified channel
*
* @param message The message you want to send
*/
public void reply(String message) {
reply(new MessageBuilder(message).build());
}
/**
* Replies a simple success message
*
* @param title The title of the message
* @param description The description of the message
* @param translate Choose which values should be translated (title, description, both, nothing)
* @param parameters Optional translation parameters for the description
*/
public void success(String title, String description, Translate translate, Object... parameters) {
simple(MessageType.SUCCESS, title, description, translate, parameters);
}
/**
* Replies a simple error message
*
* @param title The title of the message
* @param description The description of the message
* @param translate Choose which values should be translated (title, description, both, nothing)
* @param parameters Optional translation parameters for the description
*/
public void error(String title, String description, Translate translate, Object... parameters) {
simple(MessageType.ERROR, title, description, translate, parameters);
}
/**
* Replies a simple primary message
*
* @param title The title of the message
* @param description The description of the message
* @param translate Choose which values should be translated (title, description, both, nothing)
* @param parameters Optional translation parameters for the description
*/
public void primary(String title, String description, Translate translate, Object... parameters) {
simple(MessageType.PRIMARY, title, description, translate, parameters);
}
/**
* Replies a simple warning message
*
* @param title The title of the message
* @param description The description of the message
* @param translate Choose which values should be translated (title, description, both, nothing)
* @param parameters Optional translation parameters for the description
*/
public void warning(String title, String description, Translate translate, Object... parameters) {
simple(MessageType.WARNING, title, description, translate, parameters);
}
/**
* Replies a simple success message with only the translation string
* <p>
* This automatically adds <b>.title</b> and <b>.description</b> to the translation string
*
* @param translationString The translation string (for example bot.info)
* @param parameters All translation parameters for the description of the message
*/
public void success(String translationString, Object... parameters) {
success(translationString + ".title", translationString + ".description", Translate.BOTH, parameters);
}
/**
* Replies a simple error message with only the translation string
* <p>
* This automatically adds <b>.title</b> and <b>.description</b> to the translation string
*
* @param translationString The translation string (for example bot.info)
* @param parameters All translation parameters for the description of the message
*/
public void error(String translationString, Object... parameters) {
error("bot.error", translationString, Translate.BOTH, parameters);
}
/**
* Replies a simple primary message with only the translation string
* <p>
* This automatically adds <b>.title</b> and <b>.description</b> to the translation string
*
* @param translationString The translation string (for example bot.info)
* @param parameters All translation parameters for the description of the message
*/
public void primary(String translationString, Object... parameters) {
primary(translationString + ".title", translationString + ".description", Translate.BOTH, parameters);
}
/**
* Replies a simple warning message with only the translation string
* <p>
* This automatically adds <b>.title</b> and <b>.description</b> to the translation string
*
* @param translationString The translation string (for example bot.info)
* @param parameters All translation parameters for the description of the message
*/
public void warning(String translationString, Object... parameters) {
warning(translationString + ".title", translationString + ".description", Translate.BOTH, parameters);
}
/**
* Replies directly from the {@link GuildEventController#custom} method
*
* @param type The type of the message (for example primary or error)
* @param title The title of the message
* @param description The description of the message
* @param translate Choose which values should be translated (title, description, both, nothing)
* @param parameters Optional translation parameters for the description
*/
public void simple(MessageType type, String title, String description, Translate translate, Object... parameters) {
custom(type, title, description, translate, parameters).send();
}
/**
* Prepares a custom response builder
*
* @param type The type of the message (for example primary or error)
* @param title The title of the message
* @param description The description of the message
* @param translate Choose which values should be translated (title, description, both, nothing)
* @param parameters Optional translation parameters for the description
* @return the built response builder
*/
public DefaultResponseBuilder custom(MessageType type, String title, String description, Translate translate, Object... parameters) {
return custom(type)
.withTitle((translate == Translate.BOTH || translate == Translate.ONLY_TITLE) ? api.translate(title, getLanguage()) : title)
.withDescription((translate == Translate.BOTH || translate == Translate.ONLY_DESCRIPTION) ?
api.translate(description, getLanguage(), parameters) : String.format(description, parameters));
}
/**
* Sends a message with translated title
*
* @param type The type of the message (for example primary or error)
* @param titleTranslation The title translation string
* @param fields The message fields
* @param titleParameters The parameters used for the title
*/
public void custom(MessageType type, String titleTranslation, ArrayList<MessageField> fields, Object... titleParameters) {
try {
custom(type).withTitle(api.translate(titleTranslation, getLanguage(), titleParameters)).withFields(fields).send();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Prepares the {@link DefaultResponseBuilder} with a translated title and description
* <p>
* This automatically adds <b>.title</b> and <b>.description</b> to the translation string
*
* @param type The type of the message (for example primary or error)
* @param translationString The translation string you want to use
* @param parameters The parameters used in the translation
* @return the built {@link DefaultResponseBuilder}
*/
public DefaultResponseBuilder custom(MessageType type, String translationString, Object... parameters) {
return custom(type, translationString + ".title", translationString + ".description", Translate.BOTH, parameters);
}
/**
* Prepares the {@link DefaultResponseBuilder} so you can edit it completely
*
* @param messageType The type of the message (for example primary or error)
* @return the built {@link DefaultResponseBuilder} with prefilled trigger and color
*/
public DefaultResponseBuilder custom(MessageType messageType) {
return new DefaultResponseBuilder(this, trigger).withColor(messageType);
}
/**
* Gets the defined event
*
* @return the event
*/
public Event getEvent() {
return event;
}
/**
* Gets the guild language
* <p>
* Created to not check the guild language in every second
*
* @return the current guild language
*/
public String getLanguage() {
return translationLanguage == null ? api.getBotManager().getGuildManager().getLanguage(guild) : translationLanguage;
}
}

View File

@ -0,0 +1,37 @@
package xyz.sheepstar.util.bot.command;
public class PublicCommandException extends Exception {
private final String translationString;
private final Object[] translationParameters;
/**
* Basic constructor of the {@link PublicCommandException}
*
* @param translationString The translation string of the message (embed)
* @param translationParameters The optional objects you want to pass in
*/
public PublicCommandException(String translationString, Object... translationParameters) {
this.translationString = translationString;
this.translationParameters = translationParameters;
}
/**
* Gets the translation string
*
* @return the translation string
*/
public String getTranslationString() {
return translationString;
}
/**
* Gets the translation parameters
*
* @return the translation parameters
*/
public Object[] getTranslationParameters() {
return translationParameters;
}
}

View File

@ -0,0 +1,32 @@
package xyz.sheepstar.util.bot.command;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
public class SyntaxBuilder {
private final GuildCommand command;
private final OptionData syntaxElement;
public SyntaxBuilder(GuildCommand command, OptionType type, String name, String description) {
this.command = command;
syntaxElement = new OptionData(type, name.toLowerCase(), description);
}
public SyntaxBuilder required(boolean required) {
syntaxElement.setRequired(required);
return this;
}
public SyntaxBuilder addChoice(String name, String value) {
syntaxElement.addChoice(name, value);
return this;
}
public void add() {
command.addSyntaxElement(syntaxElement);
}
}

View File

@ -0,0 +1,23 @@
package xyz.sheepstar.util.bot.command.annotations;
import xyz.sheepstar.util.bot.permission.PermissionNode;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandMeta {
String[] aliases();
String[] subAliases() default {};
PermissionNode permission() default PermissionNode.DEFAULT;
String description();
String requiredSetting() default "";
String requiredSettingValue() default "yes";
}

View File

@ -0,0 +1,92 @@
package xyz.sheepstar.util.bot.command.general;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import org.jetbrains.annotations.NotNull;
import xyz.sheepstar.util.bot.command.Arguments;
import xyz.sheepstar.util.bot.command.GuildCommand;
import xyz.sheepstar.util.bot.command.GuildEventController;
import java.util.ArrayList;
import java.util.HashMap;
public abstract class GeneralGuildCommand extends GuildCommand {
@Override
public void execute(GuildEventController event, Arguments args) throws Exception {
execute(event, args, args.getString("modulename"));
}
@Override
public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) {
api.getScheduledExecutorPool().executeInstant("SR-PreparePool", () -> {
if (event.getMessage().getAuthor().isBot()) return;
String messageInput = event.getMessage().getContentRaw()
.replaceAll("<@!?(\\d+)>", "$1")
.replaceAll("<@&(\\d+)>", "$1")
.replaceAll("<#(\\d+)>", "$1")
.replaceAll("\"", "");
GuildEventController controller = new GuildEventController(event.getAuthor(), event.getMember(), event.getChannel(), event.getGuild(), this.getClass())
.useEvent(event);
ArrayList<String> parts = getPartsFromInput(messageInput);
if (!parts.get(0).startsWith(jda.getSelfUser().getId())) {
if (!api.getConfig().getCommandConfiguration().isPrefixEnabled()) return;
String module = getModuleNameByInput(event.getGuild(), event.getMessage().getContentRaw());
parts.add(module);
String modulePrefix = moduleManager.getPrefix(event.getGuild(), module);
if (!event.getMessage().getContentRaw().startsWith(modulePrefix)) return;
if (!aliases.contains(parts.get(0).substring(modulePrefix.length()).toLowerCase())) return;
if (commandMeta.subAliases().length != 0 && !subAliases.contains(parts.get(1))) return;
} else {
if (!api.getConfig().getCommandConfiguration().isPingEnabled()) return;
if (!aliases.contains(parts.get(1))) return;
if (commandMeta.subAliases().length != 0 && !subAliases.contains(parts.get(2))) return;
}
api.getScheduledExecutorPool().executeInstant("SR-CommandPool", () -> runSecure(controller, () ->
prepareExecute(controller, getArgumentsFromInput(parts))));
});
}
public void generalUsage() {
}
public abstract void execute(GuildEventController event, Arguments args, String moduleName) throws Exception;
@Override
public boolean isEnabled(Guild guild) {
return true;
}
@Override
public void usage() {
usage("modulename", "The name of the module you want to use").required(true).add();
generalUsage();
}
/**
* Gets a module by the message input
*
* @param guild The guild you want to use
* @param input The input you want to get the module from
* @return the name of the module
*/
public String getModuleNameByInput(Guild guild, String input) {
for (HashMap<String, Object> module : moduleManager.getModules(guild))
if (input.startsWith((String) module.get("prefix"))) return (String) module.get("moduleID");
return null;
}
}

View File

@ -0,0 +1,35 @@
package xyz.sheepstar.util.bot.emote;
public enum INTERN_EMOTE {
INFO(888142370904883250L),
NEW(888142370846146580L),
NITRO(888142372465168394L),
UNDERAGE(858746101581742130L),
ARROW_RIGHT(888142370808422440L),
ARROW_LEFT(888142370770649109L),
CHECK(888142371487903754L),
STAR_COIN(911717404990668830L),
ERROR(888142370535796837L);
private final long emoteID;
/**
* Basic constructor of the {@link INTERN_EMOTE}
*
* @param emoteID The id of the emote
*/
INTERN_EMOTE(long emoteID) {
this.emoteID = emoteID;
}
/**
* Gets the ID of the emote
*
* @return the id of the emote
*/
public long getID() {
return emoteID;
}
}

View File

@ -0,0 +1,24 @@
package xyz.sheepstar.util.bot.listener;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import org.jetbrains.annotations.NotNull;
import xyz.sheepstar.util.bot.command.GuildEventController;
public abstract class GuildListener extends ListenerBasics {
@Override
public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) {
GuildEventController controller = new GuildEventController(event.getAuthor(), event.getMember(), event.getChannel(), event.getGuild(), this.getClass())
.useEvent(event);
api.getScheduledExecutorPool().executeInstant("SR-ListenerPool", () -> runSecure(controller, () ->
messageReceived(controller, event.getMessage())));
}
public void messageReceived(GuildEventController event, Message message) throws Exception {
}
}

View File

@ -0,0 +1,298 @@
package xyz.sheepstar.util.bot.listener;
import de.gnmyt.sqltoolkit.storage.SQLTable;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
import net.dv8tion.jda.api.exceptions.HierarchyException;
import net.dv8tion.jda.api.exceptions.InsufficientPermissionException;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import xyz.sheepstar.core.SheepstarCore;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.bot.command.CommandRunnable;
import xyz.sheepstar.util.bot.command.GuildEventController;
import xyz.sheepstar.util.bot.command.PublicCommandException;
import xyz.sheepstar.util.bot.emote.INTERN_EMOTE;
import xyz.sheepstar.util.bot.manager.sql.ModuleManager;
import xyz.sheepstar.util.mapper.JSONContent;
import xyz.sheepstar.util.sql.SheepDatabase;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ListenerBasics extends ListenerAdapter {
public JDA jda = SheepstarCore.getSheepstar().getJDA();
public SheepstarImpl api = SheepstarCore.getSheepstar();
protected ModuleManager moduleManager = api.getBotManager().getModuleManager();
/**
* Gets a module by its class
*
* @param className The classname as a string
* @return the name of the module
*/
public String getModuleByClass(String className) {
return api.getModuleName(className);
}
/**
* Gets a module by its class
*
* @param clazz The class under which the module is registered
* @return the name of the module
*/
public String getModuleByClass(Class<? extends ListenerAdapter> clazz) {
return api.getModuleName(clazz.getName());
}
/**
* Gets the module name of the superclass
*
* @return the name of the module
*/
public String getModule() {
return api.getModuleName(super.getClass().getName());
}
/**
* Translates a translationString to the provided language
*
* @param translationString The string you want to translate
* @param languageCode The language you want to translate the string to
* @param variables The optional variables you need to pass to the string
* @return the translated message
*/
public String translate(String translationString, String languageCode, Object... variables) {
return api.translate(translationString, languageCode, variables);
}
/**
* Translates a translationString to the provided language
*
* @param translationString The string you want to translate
* @param guild The guild you want to get the language from
* @param variables The optional variables you need to pass to the string
* @return the translated message
*/
public String translate(String translationString, Guild guild, Object... variables) {
return translate(translationString, getLanguage(guild), variables);
}
/**
* Gets the language of an guild
*
* @param guild The guild you want to get the language from
* @return The language in a lower case
*/
public String getLanguage(Guild guild) {
return api.getBotManager().getGuildManager().getLanguage(guild);
}
/**
* Gets the prefix of the module from the superclass
*
* @param guild The guild you want to the the prefix from
* @return the module prefix
*/
public String getPrefix(Guild guild) {
return api.getBotManager().getModuleManager().getPrefix(guild, getModuleByClass(super.getClass()));
}
/**
* Runs a runnable without printing the stacktrace if an error happens
*
* @param run The runnable you want to run
*/
public void runIgnored(Runnable run) {
try {
run.run();
} catch (Exception ignored) {
}
}
/**
* Runs a {@link CommandRunnable} in a secure try-catch block to inform the user about errors
*
* @param controller The {@link GuildEventController} from the events
* @param runnable The action you want to run
*/
public void runSecure(GuildEventController controller, CommandRunnable runnable) {
try {
runnable.run();
} catch (PublicCommandException e) {
controller.error(e.getTranslationString(), e.getTranslationParameters());
} catch (InsufficientPermissionException e) {
controller.error("bot.insufficient_permission", e.getPermission().getName());
} catch (HierarchyException e) {
controller.error("bot.hierarchy_error");
} catch (ErrorResponseException e) {
controller.error("bot.response_error", e.getMeaning(), e.getErrorCode());
} catch (Exception e) {
if (api.isDebugModeEnabled()) e.printStackTrace();
controller.error("bot.unexpected_error", "GuildMessageReceivedError", e.getMessage(),
e.getStackTrace()[0].getClassName() + "#" + e.getStackTrace()[0].getLineNumber());
}
}
/**
* Runs a runnable asynchronously
*
* @param run The runnable you want to run
*/
public void runAsync(Runnable run) {
CompletableFuture.runAsync(run);
}
/**
* Runs a runnable ignored and asynchronously
*
* @param run The runnable you want to run
*/
public void runAsyncIgnored(Runnable run) {
runAsync(() -> runIgnored(run));
}
/**
* Gets an emote mention by name
*
* @param emoteName The name of the emote
* @return the emote mention
*/
public String getEmoteStringByName(String emoteName) {
return getEmoteByName(emoteName, false).getAsMention();
}
/**
* Gets a emote mention by id
*
* @param emoteID The id of the emote
* @return the emote mention
*/
public String getEmoteStringById(String emoteID) {
return getEmoteById(emoteID).getAsMention();
}
/**
* Gets an emote string by the {@link INTERN_EMOTE} enum
*
* @param emote The emote you want to get
* @return the emote as a string
*/
public String getEmoteString(INTERN_EMOTE emote) {
return getEmoteStringById(String.valueOf(emote.getID()));
}
/**
* Gets an emote by a name
*
* @param emoteName The name of the emote
* @param ignoreCase Search with ignoring the case?
* @return the emote
*/
public Emote getEmoteByName(String emoteName, boolean ignoreCase) {
try {
return jda.getEmotesByName(emoteName, ignoreCase).get(0);
} catch (Exception err) {
return getEmoteById("813810764405407814");
}
}
/**
* Gets an emote by id
*
* @param emoteID The id of the emote
* @return the emote
*/
public Emote getEmoteById(String emoteID) {
try {
return jda.getEmoteById(emoteID);
} catch (Exception err) {
return jda.getEmoteById(813810764405407814L);
}
}
/**
* Gets an emote by the {@link INTERN_EMOTE} enum
*
* @param emote The emote you want to get
* @return the emote as an emote object
*/
public Emote getEmote(INTERN_EMOTE emote) {
return getEmoteById(String.valueOf(emote.getID()));
}
/**
* Checks if the module from the superclass is enabled
*
* @param guild The guild you want to check
* @return a boolean that says if the module is enabled
*/
public boolean isEnabled(Guild guild) {
return moduleManager.isEnabled(guild, getModuleByClass(super.getClass()));
}
/**
* Shortcut for getting the database
*
* @return the database
*/
public SheepDatabase database() {
return api.getDatabase();
}
/**
* Shortcut for getting a SheepTable
*
* @param table The table you want to get
* @return the table
*/
public SQLTable table(Class<? extends SQLTable> table) {
return database().getTableFactory().getTable(table);
}
/**
* Parses a json string into a json content instance
*
* @param content The json content you want to parse
* @return A new instance of the json content
*/
public JSONContent parseJSON(String content) {
return new JSONContent(content);
}
/**
* Gets the time/date by a string
*
* @param text The text you want to parse
* Example: 21d5h2m
* @return the string as a {@link Date}
*/
public Date getTimeFromString(String text) {
Matcher m = Pattern.compile("[1-9]+[a-z]").matcher(text);
List<String> list = new ArrayList<>();
while (m.find()) list.add(m.group());
Calendar calendar = Calendar.getInstance();
list.forEach(pattern -> {
if (pattern.endsWith("d"))
calendar.add(Calendar.DATE, Integer.parseInt(pattern.replace("d", "")));
else if (pattern.endsWith("h"))
calendar.add(Calendar.HOUR, Integer.parseInt(pattern.replace("h", "")));
else if (pattern.endsWith("m"))
calendar.add(Calendar.MINUTE, Integer.parseInt(pattern.replace("m", "")));
});
return calendar.getTime();
}
}

View File

@ -0,0 +1,47 @@
package xyz.sheepstar.util.bot.listener;
public class ListenerInfo {
private String moduleName;
private Object listener;
/**
* Gets the listener you set
*
* @return The listener
*/
public Object getListener() {
return listener;
}
/**
* Sets the listener object
*
* @param listener The new listener object
* @return this class
*/
public ListenerInfo setListener(Object listener) {
this.listener = listener;
return this;
}
/**
* Gets the name of the module
*
* @return The name of the module
*/
public String getModuleName() {
return moduleName;
}
/**
* Sets the name of the module
*
* @param moduleName The new name of the module
* @return this class
*/
public ListenerInfo setModuleName(String moduleName) {
this.moduleName = moduleName;
return this;
}
}

View File

@ -0,0 +1,111 @@
package xyz.sheepstar.util.bot.manager;
import de.gnmyt.sqltoolkit.factory.TableFactory;
import net.dv8tion.jda.api.entities.Activity;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.bot.manager.sql.*;
import xyz.sheepstar.util.bot.updater.StatusUpdater;
public class BotManager {
private final TableFactory tableFactory;
private final SheepstarImpl api;
private StatusUpdater statusUpdater;
/**
* Loads an creates all managers
*
* @param api The sheepstar instance
*/
public BotManager(SheepstarImpl api) {
this.tableFactory = api.getDatabase().getTableFactory();
this.api = api;
// Register sql managers
tableFactory
.register(new GuildManager())
.register(new TranslationManager())
.register(new ModuleManager())
.register(new LanguageManager())
.register(new SettingsInfoManager())
.register(new SettingsManager())
.register(new CommandMetaManager());
initAutoUpdater();
}
/**
* Initialises the auto status updater
*/
private void initAutoUpdater() {
statusUpdater = new StatusUpdater(api);
api.getConfig().getActivities().forEach(action ->
statusUpdater.addActivity(Activity.of(action.getType(), action.getName())));
statusUpdater.start();
}
/**
* Gets the auto updater
*
* @return the status updater
*/
public StatusUpdater getAutoUpdater() {
return statusUpdater;
}
/**
* Gets the guild manager
*
* @return the guild manager
*/
public GuildManager getGuildManager() {
return (GuildManager) tableFactory.getTable(GuildManager.class);
}
/**
* Gets the translation manager
*
* @return the translation manager
*/
public TranslationManager getTranslationManager() {
return (TranslationManager) tableFactory.getTable(TranslationManager.class);
}
/**
* Gets the module manager
*
* @return the module manager
*/
public ModuleManager getModuleManager() {
return (ModuleManager) tableFactory.getTable(ModuleManager.class);
}
/**
* Gets the language manager
*
* @return the language manager
*/
public LanguageManager getLanguageManager() {
return (LanguageManager) tableFactory.getTable(LanguageManager.class);
}
/**
* Gets the settings info manager
*
* @return the settings info manager
*/
public SettingsInfoManager getSettingsInfoManager() {
return (SettingsInfoManager) tableFactory.getTable(SettingsInfoManager.class);
}
/**
* Gets the settings manager
*
* @return the settings manager
*/
public SettingsManager getSettingsManager() {
return (SettingsManager) tableFactory.getTable(SettingsManager.class);
}
}

View File

@ -0,0 +1,60 @@
package xyz.sheepstar.util.bot.manager;
import xyz.sheepstar.util.Sheepstar;
import xyz.sheepstar.util.bot.command.GuildCommand;
public class ImportManager {
private final Sheepstar api;
private final String moduleName;
/**
* Basic constructor for the ImportManager
*
* @param api The sheepstar api
* @param moduleName The name of the module
*/
public ImportManager(Sheepstar api, String moduleName) {
this.api = api;
this.moduleName = moduleName;
}
/**
* Registers a Listener
*
* @param listener The Listener you want to register
*/
public void registerListener(Object listener) {
api.registerListener(moduleName, listener);
}
/**
* Registers a command
*
* @param command The command you want to register
*/
public void registerCommand(GuildCommand command) {
api.registerCommand(moduleName, command);
}
/**
* Registers multiple listeners
*
* @param listeners The listener you want to register
*/
public void registerListeners(Object... listeners) {
for (Object current : listeners)
registerListener(current);
}
/**
* Registers multiple commands
*
* @param commands The commands you want to register
*/
public void registerCommands(GuildCommand... commands) {
for (GuildCommand command : commands)
registerCommand(command);
}
}

View File

@ -0,0 +1,68 @@
package xyz.sheepstar.util.bot.manager.sql;
import xyz.sheepstar.util.sql.SheepManager;
public class CommandMetaManager extends SheepManager {
@Override
protected String tableName() {
return "command_meta";
}
@Override
protected void tableFields() {
custom("module").add();
custom("name").add();
custom("sub").allowNull(true).add();
custom("description").add();
}
/**
* Adds a command to the dataset
*
* @param moduleName The name of the module from the command
* @param commandName The name of the command
* @param subAlias The sub alias of the command
* @param description The description of the command
*/
public void addCommand(String moduleName, String commandName, String subAlias, String description) {
insert().value("module", moduleName).value("name", commandName).value("sub", subAlias).value("description", description).execute();
}
/**
* Adds a command to the dataset
*
* @param moduleName The name of the module from the command
* @param commandName The name of the command
* @param description The description of the command
*/
public void addCommand(String moduleName, String commandName, String description) {
insert().value("module", moduleName).value("name", commandName).value("description", description).execute();
}
/**
* Deletes a command from the dataset
*
* @param commandName The name of the command you want to delete
* @param subAlias The sub alias of the command you want to delete
*/
public void deleteCommand(String commandName, String subAlias) {
delete().where("name", commandName).where("sub", subAlias).execute();
}
/**
* Deletes a command from the dataset
*
* @param commandName The name of the command you want to delete
*/
public void deleteCommand(String commandName) {
delete().where("name", commandName).execute();
}
/**
* Clears the list of commands
*/
public void clear() {
delete().execute();
}
}

View File

@ -0,0 +1,121 @@
package xyz.sheepstar.util.bot.manager.sql;
import de.gnmyt.sqltoolkit.types.SQLType;
import net.dv8tion.jda.api.entities.Guild;
import xyz.sheepstar.util.sql.SheepManager;
import java.util.HashMap;
public class GuildManager extends SheepManager {
@Override
public String tableName() {
return "guilds";
}
@Override
public void tableFields() {
custom("guildID").type(SQLType.VARCHAR).length(20).add();
custom("coins").type(SQLType.INTEGER).length(50).defaultValue("1000").add();
custom("language").type(SQLType.VARCHAR).length(3).defaultValue("en").add();
}
/**
* Checks if a guild is registered
*
* @param guild The guild you want to check
* @return a boolean that says if the guild is registered
*/
public boolean isRegistered(Guild guild) {
return containsRow("guildID", guild.getId());
}
/**
* Registers a guild
*
* @param guild The guild you want to register
*/
public void register(Guild guild) {
insert().value("guildID", guild.getId()).execute();
}
/**
* Unregisters a guild
*
* @param guild The guild you want to unregister
*/
public void unregister(Guild guild) {
delete("guildID", guild.getId());
}
/**
* Gets the language of the guild
*
* @param guild The guild you want to get the language from
* @return the language in lower case
*/
public String getLanguage(Guild guild) {
if (!isRegistered(guild)) register(guild);
return getLowerString("guildID", guild.getId(), "language");
}
/**
* Gets the coins of the guild
*
* @param guild The guild you want to get the coins from
* @return the coins of the guild
*/
public String getCoins(Guild guild) {
if (!isRegistered(guild)) register(guild);
return getString("guildID", guild.getId(), "coins");
}
/**
* Gets the coins of the guild and parses them to a integer
*
* @param guild The guild you want to get the coins from
* @return the coins of the guild
*/
public int getCoinsInt(Guild guild) {
return Integer.parseInt(getCoins(guild));
}
/**
* Gets a lost of all infos about the guild
*
* @param guild The guild you want to get the info from
* @return an info about the guild
*/
public HashMap<String, Object> getInfo(Guild guild) {
if (!isRegistered(guild)) register(guild);
return select().where("guildID", guild.getId()).getResult().getList().get(0);
}
/**
* Updates the language of the guild
*
* @param guild The guild you want to change the language
* @param toLanguage The new language you want to have
*/
public void updateLanguage(Guild guild, String toLanguage) {
if (!isRegistered(guild)) register(guild);
updateString("guildID", guild.getId(), "language", toLanguage.toLowerCase());
}
/**
* Updates coins of the guild
*
* @param guild The guild you want to use
* @param newCoins The new amount of coins you want to set
*/
public void updateCoins(Guild guild, String newCoins) {
if (!isRegistered(guild)) register(guild);
try {
Integer.parseInt(newCoins);
} catch (Exception e) {
newCoins = getCoins(guild);
}
updateString("guildID", guild.getId(), "coins", newCoins);
}
}

View File

@ -0,0 +1,84 @@
package xyz.sheepstar.util.bot.manager.sql;
import net.dv8tion.jda.api.entities.Emoji;
import xyz.sheepstar.util.sql.SheepManager;
import java.util.ArrayList;
import java.util.HashMap;
public class LanguageManager extends SheepManager {
@Override
protected String tableName() {
return "languages";
}
@Override
protected void tableFields() {
custom("code").length(5).add();
custom("name").length(25).add();
custom("emoji").add();
}
/**
* Checks if the provided language exists
*
* @param code The language you want to check
* @return a boolean that says if the language is valid/exists
*/
public boolean exists(String code) {
return containsRow("code", code);
}
/**
* Creates a new language
*
* @param code The language code
* @param name The name of the language
* @param emoji The emoji of the language
*/
public void create(String code, String name, String emoji) {
if (exists(code)) return;
insert().value("code", code).value("name", name.toLowerCase()).value("emoji", emoji).execute();
}
/**
* Deletes a language
*
* @param code The language you want to delete
*/
public void delete(String code) {
if (!exists(code)) return;
delete().where("code", code).execute();
}
/**
* Gets all languages that currently exists
*
* @return the list of languages
*/
public ArrayList<HashMap<String, Object>> getLanguages() {
return select().getResult().getList();
}
/**
* Gets the name of the language
*
* @param code The language code
* @return The name of the language
*/
public String getName(String code) {
return getCamelString("code", code, "name");
}
/**
* Gets the emoji from the language
*
* @param code The language you want to get
* @return the emoji
*/
public Emoji getEmoji(String code) {
return Emoji.fromUnicode(getString("code", code, "emoji"));
}
}

View File

@ -0,0 +1,136 @@
package xyz.sheepstar.util.bot.manager.sql;
import de.gnmyt.sqltoolkit.types.SQLType;
import net.dv8tion.jda.api.entities.Guild;
import xyz.sheepstar.util.sql.SheepManager;
import java.util.ArrayList;
import java.util.HashMap;
public class ModuleManager extends SheepManager {
@Override
protected String tableName() {
return "modules_activated";
}
@Override
protected void tableFields() {
custom("moduleID").type(SQLType.VARCHAR).length(255).add();
custom("guildID").type(SQLType.VARCHAR).length(25).add();
custom("prefix").type(SQLType.VARCHAR).length(10).add();
}
/**
* Checks if the module is enabled
*
* @param guildID The guild you want to check
* @param moduleID The module name
* @return a boolean that says if the module is enabled
*/
public boolean isEnabled(String guildID, String moduleID) {
return select().where("guildID", guildID).where("moduleID", moduleID).getResult().getRowCount() == 1;
}
/**
* Checks if the module is enabled
*
* @param guild The guild you want to check
* @param moduleID The module name
* @return a boolean that says if the module is enabled
*/
public boolean isEnabled(Guild guild, String moduleID) {
return isEnabled(guild.getId(), moduleID);
}
/**
* Enables a module on a guild
*
* @param guildID The guild on which you want to enable the module
* @param moduleID The module name
* @param prefix The prefix you want the module to have
*/
public void enableModule(String guildID, String moduleID, String prefix) {
if (isEnabled(guildID, moduleID)) return;
insert().value("guildID", guildID).value("moduleID", moduleID).value("prefix", prefix).execute();
}
/**
* Enables a module on a guild
*
* @param guild The guild on which you want to enable the module
* @param moduleID The module name
* @param prefix The prefix you want the module to have
*/
public void enableModule(Guild guild, String moduleID, String prefix) {
enableModule(guild.getId(), moduleID, prefix);
}
/**
* Disables a module on a guild
*
* @param guildID The guild on which you want to disable the module
* @param moduleID The name of the module
*/
public void disableModule(String guildID, String moduleID) {
if (!isEnabled(guildID, moduleID)) return;
delete().where("guildID", guildID).where("moduleID", moduleID).execute();
}
/**
* Disables a module on a guild
*
* @param guild The guild on which you want to disable the module
* @param moduleID The name of the module
*/
public void disableModule(Guild guild, String moduleID) {
disableModule(guild.getId(), moduleID);
}
/**
* Gets the prefix of an module in a guild
*
* @param guildID The guild you want to get the module prefix from
* @param moduleID The module name
* @return the prefix of the module
*/
public String getPrefix(String guildID, String moduleID) {
if (!isEnabled(guildID, moduleID)) return null;
return select().where("guildID", guildID).where("moduleID", moduleID).getResult().getString("prefix");
}
/**
* Updates the prefix of the module
*
* @param guild The guild you want to change the prefix from
* @param moduleID The module you want to change the prefix from
* @param newPrefix The new prefix the module should have
*/
public void updatePrefix(Guild guild, String moduleID, String newPrefix) {
if (!isEnabled(guild, moduleID)) return;
update().where("guildID", guild.getId()).where("moduleID", moduleID).set("prefix", newPrefix).execute();
}
/**
* Gets the prefix of an module in a guild
*
* @param guild The guild you want to get the module prefix from
* @param moduleID The module name
* @return the prefix of the module
*/
public String getPrefix(Guild guild, String moduleID) {
return getPrefix(guild.getId(), moduleID);
}
/**
* Gets all modules from a guild
*
* @param guild The guild you want to use
* @return a list of modules enabled in the guild
*/
public ArrayList<HashMap<String, Object>> getModules(Guild guild) {
return select().where("guildID", guild.getId()).getResult().getList();
}
}

View File

@ -0,0 +1,140 @@
package xyz.sheepstar.util.bot.manager.sql;
import de.gnmyt.sqltoolkit.types.SQLType;
import xyz.sheepstar.util.sql.SheepManager;
import java.util.ArrayList;
import java.util.HashMap;
public class SettingsInfoManager extends SheepManager {
@Override
protected String tableName() {
return "settings_infos";
}
@Override
protected void tableFields() {
custom("moduleName").type(SQLType.VARCHAR).length(255).add();
custom("settingString").type(SQLType.VARCHAR).length(255).add();
custom("descriptionString").type(SQLType.VARCHAR).length(255).add();
custom("allowedValues").type(SQLType.VARCHAR).length(255).allowNull(true).add();
custom("defaultValue").type(SQLType.VARCHAR).length(255).add();
}
/**
* Gets all the info settings from the table
*
* @param moduleName The name of the module
* @return a list of all settings
*/
public ArrayList<HashMap<String, Object>> getSettings(String moduleName) {
return select().where("moduleName", moduleName).getResult().getList();
}
/**
* Checks if a info exists in the table
*
* @param moduleName The name of the module
* @param setting The name of the setting you want to check
* @return a boolean that says if the info exists in the table
*/
public boolean existsInfo(String moduleName, String setting) {
return select().where("moduleName", moduleName).where("settingString", setting).getResult().getRowCount() == 1;
}
/**
* Inserts a new info to the table
*
* @param moduleName The name of the module you want to use
* @param setting The name of the setting you want to use
* @param descriptionString The description you want to insert
* @param defaultValue The default value you want to insert
* @param allowedValues The allowed values of the info
*/
public void createInfo(String moduleName, String setting, String descriptionString, String defaultValue, String allowedValues) {
if (existsInfo(moduleName, setting)) return;
insert().value("moduleName", moduleName).value("settingString", setting).value("descriptionString", descriptionString)
.value("defaultValue", defaultValue).value("allowedValues", allowedValues).execute();
}
/**
* Deletes a info from the table
*
* @param moduleName The name of the module
* @param setting The setting you want to delete
*/
public void deleteInfo(String moduleName, String setting) {
if (!existsInfo(moduleName, setting)) return;
delete().where("moduleName", moduleName).where("settingString", setting).execute();
}
/**
* Gets the description from a setting
*
* @param moduleName The name of the module
* @param setting The setting from which you want the description from
* @return the description of the setting
*/
public String getDescription(String moduleName, String setting) {
return select().where("moduleName", moduleName).where("settingString", setting).getResult().getString("descriptionString");
}
/**
* Gets the default value of a setting
*
* @param moduleName The name of the module
* @param setting The setting from which you want the description from
* @return the default value of the setting
*/
public String getDefaultValue(String moduleName, String setting) {
return select().where("moduleName", moduleName).where("settingString", setting).getResult().getString("defaultValue");
}
/**
* Gets the allowed values of a string
*
* @param moduleName The name of the module
* @param setting The setting from which you want the values from
* @return the allowed values
*/
public String[] getAllowedValues(String moduleName, String setting) {
String allowedValues = select().where("moduleName", moduleName)
.where("settingString", setting).getResult().getString("allowedValues");
if (allowedValues == null) return null;
return allowedValues.split(",");
}
/**
* Checks if a value is allowed
*
* @param moduleName The name of the module
* @param setting The setting you want to check
* @param value The value you want to check
* @return A boolean that says if the value provided is allowed
*/
public boolean isAllowed(String moduleName, String setting, String value) {
String[] allowedValues = getAllowedValues(moduleName, setting);
if (allowedValues == null) return true;
for (String currentValue : allowedValues)
if (value.matches(currentValue)) return true;
return false;
}
/**
* Gets the allowed values as a string
*
* @param moduleName The name of the module
* @param setting The setting you want to get
* @return The allowed values as a string
*/
public String getAllowedValuesPretty(String moduleName, String setting) {
StringBuilder values = new StringBuilder();
for (String current : getAllowedValues(moduleName, setting)) {
if (!values.toString().isEmpty()) values.append(", ");
values.append(current);
}
return values.toString();
}
}

View File

@ -0,0 +1,107 @@
package xyz.sheepstar.util.bot.manager.sql;
import de.gnmyt.sqltoolkit.types.SQLType;
import net.dv8tion.jda.api.entities.Guild;
import xyz.sheepstar.core.SheepstarCore;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.sql.SheepManager;
import java.util.HashMap;
public class SettingsManager extends SheepManager {
private final SheepstarImpl api = SheepstarCore.getSheepstar();
@Override
protected String tableName() {
return "settings";
}
@Override
protected void tableFields() {
custom("guildID").type(SQLType.VARCHAR).length(255).add();
custom("moduleName").type(SQLType.VARCHAR).length(255).add();
custom("settingString").type(SQLType.VARCHAR).length(255).add();
custom("settingValue").type(SQLType.VARCHAR).length(255).add();
}
/**
* Gets all set settings from a guild
*
* @param guild The guild from which you want the setting from
* @param module The module from which you want the setting from
* @return the settings
*/
public HashMap<String, String> getSettings(Guild guild, String module) {
return select().where("guildID", guild.getId()).where("moduleName", module).getResult()
.getMultipleList("settingString", "settingValue");
}
/**
* Checks if a setting exists
*
* @param guild The guild from which you want the setting from
* @param module The module from which you want the setting from
* @param setting The setting you want to check
* @return a boolean that says if the setting exists
*/
public boolean existsSetting(Guild guild, String module, String setting) {
return select().where("guildID", guild.getId()).where("moduleName", module).where("settingString", setting).getResult().getRowCount() == 1;
}
/**
* Gets a setting from a guild
*
* @param guild The guild from which you want the setting from
* @param module The module from which you want the setting from
* @param setting The setting you want to get
* @return the value of the setting
*/
public Object getSetting(Guild guild, String module, String setting) {
if (!existsSetting(guild, module, setting))
updateSetting(guild, module, setting, api.getBotManager().getSettingsInfoManager().getDefaultValue(module, setting));
return select().where("moduleName", module).where("guildID", guild.getId()).where("settingString", setting)
.getResult().getObject("settingValue");
}
/**
* Gets a setting from a guild in the form of a string
*
* @param guild The guild from which you want the setting from
* @param module The module from which you want the setting from
* @param setting The setting you want to get
* @return the value of the setting in form of a string
*/
public String getSettingString(Guild guild, String module, String setting) {
return getSetting(guild, module, setting).toString();
}
/**
* Inserts a setting into the table
*
* @param guild The guild you want to use
* @param module The module you want to use
* @param setting The setting you want to insert
* @param value The value you want to insert
*/
public void insertSetting(Guild guild, String module, String setting, String value) {
insert().value("guildID", guild.getId()).value("moduleName", module).value("settingString", setting)
.value("settingValue", value).execute();
}
/**
* Updates a setting from this table
*
* @param guild The guild you want to use
* @param module The module you want to use
* @param setting The setting you want to use
* @param value The value you want to update
*/
public void updateSetting(Guild guild, String module, String setting, String value) {
if (existsSetting(guild, module, setting)) {
update().where("moduleName", module).where("guildID", guild.getId()).where("settingString", setting)
.set("settingValue", value).execute();
} else insertSetting(guild, module, setting, value);
}
}

View File

@ -0,0 +1,100 @@
package xyz.sheepstar.util.bot.manager.sql;
import de.gnmyt.sqltoolkit.types.SQLType;
import xyz.sheepstar.util.sql.SheepManager;
import java.util.HashMap;
public class TranslationManager extends SheepManager {
@Override
protected String tableName() {
return "translations";
}
@Override
protected void tableFields() {
string("translationCode", 999, false, "");
custom("languageCode").type(SQLType.VARCHAR).length(5).defaultValue("en").add();
string("translation", 999, false, "");
}
/**
* Checks if a translationCode is registered
*
* @param translationCode The translation string/code
* @param languageCode The language you want to check
* @return a boolean that says if the language is registered
*/
public boolean isRegistered(String translationCode, String languageCode) {
return select()
.where("translationCode", translationCode)
.where("languageCode", languageCode)
.getResult().getRowCount() == 1;
}
/**
* Inserts a translation
*
* @param translationCode The translation code/string
* @param toLanguage The language you want to translate
* @param translation The translation itself
*/
public void translate(String translationCode, String toLanguage, String translation) {
if (isRegistered(translationCode, toLanguage)) return;
insert()
.value("translationCode", translationCode)
.value("languageCode", toLanguage)
.value("translation", translation)
.execute();
}
/**
* Inserts a translation with defaults to english
*
* @param translationCode The translation code/string
* @param translation The translation itself
*/
public void translate(String translationCode, String translation) {
translate(translationCode, "en", translation);
}
/**
* Deletes a translation by id
*
* @param id The id of the translation
*/
public void deleteTranslation(int id) {
if (containsRow("id", id)) delete("id", id);
}
/**
* Deletes a translation by code
*
* @param translationCode The translation code/string
* @param toLanguage The language
*/
public void deleteTranslation(String translationCode, String toLanguage) {
if (isRegistered(translationCode, toLanguage))
delete().where("translationCode", translationCode).where("languageCode", toLanguage).execute();
}
/**
* Gets a translation from a string
*
* @param translationString The translation code/string
* @param languageCode The language you want to get the translation from
* @param variables The objects you want to add to your translation
* @return the translation
*/
public String getTranslation(String translationString, String languageCode, Object... variables) {
HashMap<String, String> result = select().where("translationCode", translationString).getResult().getMultipleList("languageCode", "translation");
if (result.isEmpty()) return "${{" + translationString + "}}";
if (result.containsKey(languageCode))
return String.format(result.get(languageCode), variables).replace("\\n", "\n");
if (!languageCode.equals("en") && result.containsKey("en"))
return String.format(result.get("en"), variables).replace("\\n", "\n");
return "${{" + translationString + "}}";
}
}

View File

@ -0,0 +1,11 @@
package xyz.sheepstar.util.bot.permission;
public enum PermissionNode {
ADMINISTRATOR,
SUPPORTER,
BOT_OWNER,
SERVER_OWNER,
DEFAULT
}

View File

@ -0,0 +1,107 @@
package xyz.sheepstar.util.bot.updater;
import net.dv8tion.jda.api.entities.Activity;
import xyz.sheepstar.util.SheepstarImpl;
import java.util.ArrayList;
public class StatusUpdater {
private final SheepstarImpl api;
private final ArrayList<Activity> activities;
private int time = 15000;
private Thread updateThread;
/**
* The default constructor of the StatusUpdater
*
* @param api The Sheepstar instance
*/
public StatusUpdater(SheepstarImpl api) {
this.api = api;
activities = new ArrayList<>();
}
/**
* Adds a activity to the status updater
*
* @param activity The activity you want to add
*/
public void addActivity(Activity activity) {
activities.add(activity);
}
/**
* Removes a activity from the status updater
*
* @param element The id of the activity you want to remove
*/
public void removeActivity(int element) {
activities.remove(element);
}
/**
* Clears all activities from the status updater
*/
public void clearActivity() {
activities.clear();
}
/**
* Stops the status updating thread
*/
public void stop() {
if (isRunning()) {
updateThread.interrupt();
updateThread = null;
}
}
/**
* Starts the status updating thread
*/
public void start() {
if (!isRunning()) {
updateThread = new Thread(this::run);
updateThread.setName("StatusUpdater");
updateThread.start();
}
}
/**
* Runs the status updating logic
*/
private void run() {
if (activities.size() > 0)
for (Activity activity : activities) {
try {
api.getJDA().getPresence().setActivity(activity);
Thread.sleep(time);
} catch (Exception ignored) {
}
}
try {
Thread.sleep(2000);
} catch (Exception ignored) {
}
run();
}
/**
* Checks if the updating thread is running
*
* @return a boolean that says if the update thread is running
*/
public boolean isRunning() {
return updateThread != null;
}
/**
* Sets the time every message changes in ms
*
* @param time The time you want to change
*/
public void setTime(int time) {
this.time = time;
}
}

View File

@ -0,0 +1,64 @@
package xyz.sheepstar.util.configuration;
public class CommandConfiguration {
private final boolean pingEnabled;
private final boolean prefixEnabled;
private final boolean slashEnabled;
private final String debugGuild;
/**
* Constructor of the {@link CommandConfiguration}
*
* @param pingEnabled Is the ping feature enabled?
* If so, the bot will react to pings
* @param prefixEnabled Is the prefix feature enabled?
* If so, the bot will react to prefix commands
* @param slashEnabled Is the slash command feature enabled?
* If so, the bot is able to use slash commands
* @param debugGuild If you want to, you can set a debug guild.
* It helps you to register commands faster
*/
public CommandConfiguration(boolean pingEnabled, boolean prefixEnabled, boolean slashEnabled, String debugGuild) {
this.pingEnabled = pingEnabled;
this.prefixEnabled = prefixEnabled;
this.slashEnabled = slashEnabled;
this.debugGuild = debugGuild;
}
/**
* Is the ping feature enabled?
*
* @return <code>true</code> if the ping feature is enabled, otherwise <code>false</code>
*/
public boolean isPingEnabled() {
return pingEnabled;
}
/**
* Is the prefix feature enabled?
*
* @return <code>true</code> if the prefix feature is enabled, otherwise <code>false</code>
*/
public boolean isPrefixEnabled() {
return prefixEnabled;
}
/**
* Is the slash feature enabled?
*
* @return <code>true</code> if the slash feature is enabled, otherwise <code>false</code>
*/
public boolean isSlashEnabled() {
return slashEnabled;
}
/**
* Gets the debug guild
*
* @return the debug guild
*/
public String getDebugGuild() {
return debugGuild;
}
}

View File

@ -0,0 +1,60 @@
package xyz.sheepstar.util.configuration;
public class DatabaseConfiguration {
private final String hostname;
private final String username;
private final String password;
private final String database;
/**
* Constructor of the {@link DatabaseConfiguration}
*
* @param hostname The hostname of your mysql connection
* @param username The username of your mysql connection
* @param password The password of your mysql connection
* @param database The database of your mysql connection
*/
public DatabaseConfiguration(String hostname, String username, String password, String database) {
this.hostname = hostname;
this.username = username;
this.password = password;
this.database = database;
}
/**
* Gets the hostname of your mysql database
*
* @return the database hostname
*/
public String getHostname() {
return hostname;
}
/**
* Gets the username of your mysql database
*
* @return the database username
*/
public String getUsername() {
return username;
}
/**
* Gets the password of the mysql database
*
* @return the database password
*/
public String getPassword() {
return password;
}
/**
* Gets the database name of the mysql database
*
* @return the database name
*/
public String getDatabase() {
return database;
}
}

View File

@ -0,0 +1,37 @@
package xyz.sheepstar.util.configuration;
public class PermissionConfiguration {
private final String[] botOwner;
private final SupporterPermissionConfiguration supporterPermissionConfiguration;
/**
* Constructor of the {@link PermissionConfiguration}
*
* @param botOwner All bot owners.
* Used to check permissions of a user
* @param supporterPermissionConfiguration The supporter permission configuration that needs to be set up
*/
public PermissionConfiguration(String[] botOwner, SupporterPermissionConfiguration supporterPermissionConfiguration) {
this.botOwner = botOwner;
this.supporterPermissionConfiguration = supporterPermissionConfiguration;
}
/**
* Gets all owners of the bot
*
* @return all owners of the bot
*/
public String[] getBotOwner() {
return botOwner;
}
/**
* Gets the supporter configuration
*
* @return the supporter configuration
*/
public SupporterPermissionConfiguration getSupporter() {
return supporterPermissionConfiguration;
}
}

View File

@ -0,0 +1,128 @@
package xyz.sheepstar.util.configuration;
import xyz.sheepstar.util.configuration.entity.SheepstarActivity;
import xyz.sheepstar.util.configuration.entity.SheepstarPool;
import java.util.ArrayList;
public class SheepstarConfiguration {
private final String token;
private final String apiUrl;
private final String apiKey;
private final String moduleDirectory;
private final DatabaseConfiguration databaseConfiguration;
private final CommandConfiguration commandConfiguration;
private final PermissionConfiguration permissionConfiguration;
private final ArrayList<SheepstarActivity> activities;
private final ArrayList<SheepstarPool> pools;
/**
* Constructor of the {@link SheepstarConfiguration}
*
* @param token The token the sheepstar bot should connect to
* @param apiUrl The api url the sheepstar bot should connect to
* @param apiKey The sheepstar api key the bot should use to get something from the server
* @param moduleDirectory The directory your modules are in
* @param databaseConfiguration The database configuration you have to set up
* @param commandConfiguration The command configuration you have to set up
* @param permissionConfiguration The permission configuration you have to set up
* @param activities The activities you want to load
* @param pools The pools you want to use
*/
public SheepstarConfiguration(String token, String apiUrl, String apiKey, String moduleDirectory, DatabaseConfiguration databaseConfiguration,
CommandConfiguration commandConfiguration, PermissionConfiguration permissionConfiguration,
ArrayList<SheepstarActivity> activities, ArrayList<SheepstarPool> pools) {
this.token = token;
this.apiUrl = apiUrl;
this.apiKey = apiKey;
this.moduleDirectory = moduleDirectory;
this.databaseConfiguration = databaseConfiguration;
this.commandConfiguration = commandConfiguration;
this.permissionConfiguration = permissionConfiguration;
this.activities = activities;
this.pools = pools;
}
/**
* Gets the sheepstar bot token
*
* @return the sheepstar bot token
*/
public String getToken() {
return token;
}
/**
* Gets the sheepstar api url
*
* @return the sheepstar api url
*/
public String getApiUrl() {
return apiUrl;
}
/**
* Gets the sheepstar api key
*
* @return the sheepstar api key
*/
public String getApiKey() {
return apiKey;
}
/**
* Gets the module directory in which all modules are located in
*
* @return the module directory
*/
public String getModuleDirectory() {
return moduleDirectory;
}
/**
* Gets the database configuration with all needed database parameters
*
* @return the database configuration
*/
public DatabaseConfiguration getDatabaseConfiguration() {
return databaseConfiguration;
}
/**
* Gets the command configuration with all needed command parameters
*
* @return the command configuration
*/
public CommandConfiguration getCommandConfiguration() {
return commandConfiguration;
}
/**
* Gets the permission configuration with all needed permission parameters
*
* @return the permission configuration
*/
public PermissionConfiguration getPermissionConfiguration() {
return permissionConfiguration;
}
/**
* Gets the activities that should be loaded
*
* @return the activities
*/
public ArrayList<SheepstarActivity> getActivities() {
return activities;
}
/**
* Gets the pools that should be used
*
* @return the pools
*/
public ArrayList<SheepstarPool> getPools() {
return pools;
}
}

View File

@ -0,0 +1,36 @@
package xyz.sheepstar.util.configuration;
public class SupporterPermissionConfiguration {
private final String guildID;
private final String roleID;
/**
* Constructor of the {@link SupporterPermissionConfiguration}
*
* @param guildID The guild id in which the supporter role is located in
* @param roleID The role id to check which user is a supporter
*/
public SupporterPermissionConfiguration(String guildID, String roleID) {
this.guildID = guildID;
this.roleID = roleID;
}
/**
* Gets the guild id
*
* @return the guild id
*/
public String getGuildID() {
return guildID;
}
/**
* Gets the role id
*
* @return the role id
*/
public String getRoleID() {
return roleID;
}
}

View File

@ -0,0 +1,38 @@
package xyz.sheepstar.util.configuration.entity;
import net.dv8tion.jda.api.entities.Activity;
public class SheepstarActivity {
private final Activity.ActivityType type;
private final String name;
/**
* Constructor of the {@link SheepstarActivity}
*
* @param type The type of the activity
* @param name The name of the activity
*/
public SheepstarActivity(Activity.ActivityType type, String name) {
this.type = type;
this.name = name;
}
/**
* Gets the type of the activity
*
* @return the type of the activity
*/
public Activity.ActivityType getType() {
return type;
}
/**
* Gets the name of the activity
*
* @return the name of the activity
*/
public String getName() {
return name;
}
}

View File

@ -0,0 +1,36 @@
package xyz.sheepstar.util.configuration.entity;
public class SheepstarPool {
private final String poolName;
private final int corePoolSize;
/**
* Constructor of the {@link SheepstarPool}
*
* @param poolName The name of the pool
* @param corePoolSize The core pool size
*/
public SheepstarPool(String poolName, int corePoolSize) {
this.poolName = poolName;
this.corePoolSize = corePoolSize;
}
/**
* Get the name of the pool
*
* @return the name of the pool
*/
public String getPoolName() {
return poolName;
}
/**
* Get the core pool size
*
* @return the core pool size
*/
public int getCorePoolSize() {
return corePoolSize;
}
}

View File

@ -0,0 +1,83 @@
package xyz.sheepstar.util.console;
import org.slf4j.Logger;
import xyz.sheepstar.core.SheepstarCore;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.log.LogManager;
import java.util.ArrayList;
import java.util.List;
public abstract class ConsoleCommand {
private final Logger LOG = LogManager.getLog(ConsoleManager.class);
protected SheepstarImpl api = SheepstarCore.getSheepstar();
ArrayList<ConsoleCommandField> usage = new ArrayList<>();
{
usage();
}
/**
* Gets the aliases of the command
*
* @return the aliases of the command
*/
public abstract List<String> getAlias();
/**
* Runs when the validation was successful
*
* @param args The list of arguments
*/
public abstract void onExecute(String[] args);
/**
* Runs when the alias matches an alias from the list
*
* @param args The list of arguments
*/
public void run(String[] args) {
if (!usage.isEmpty() && !isUsageValid(args)) {
LOG.error("Wrong usage! Please use: " + getAlias().get(0) + " " + getUsagePretty());
return;
}
onExecute(args);
}
public boolean isUsageValid(String[] args) {
for (int i = 0; i < usage.size(); i++) {
ConsoleCommandField field = usage.get(i);
if (field.isRequired() && args.length <= i) return false;
if (args.length <= i) continue;
if (field.getLength() != -1 && field.getLength() < args[i].length()) return false;
}
return true;
}
public String getUsagePretty() {
StringBuilder usageString = new StringBuilder();
usage.forEach(usage -> {
if (!usageString.toString().isEmpty()) usageString.append(" ");
String chars = usage.isRequired() ? "<%s>" : "[%s]";
usageString.append(String.format(chars, usage.getName()));
});
return usageString.toString();
}
/**
* Provides the usage of the command
*/
public void usage() {
}
public void usage(String name, int length, boolean isRequired) {
usage.add(new ConsoleCommandField(name, length, isRequired));
}
}

View File

@ -0,0 +1,76 @@
package xyz.sheepstar.util.console;
public class ConsoleCommandField {
private String name;
private int length;
private boolean isRequired;
/**
* Basic constructor for the CommandUsage
*
* @param name The name of the usage field
* @param length The length of the usage field
* @param isRequired Is the field required?
*/
public ConsoleCommandField(String name, int length, boolean isRequired) {
this.name = name;
this.length = length;
this.isRequired = isRequired;
}
/**
* Gets the field name
*
* @return the field name
*/
public String getName() {
return name;
}
/**
* Sets the field name
*
* @param name The new field name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the field length
*
* @return Gets the field length
*/
public int getLength() {
return length;
}
/**
* Sets the field length
*
* @param length The new field length
*/
public void setLength(int length) {
this.length = length;
}
/**
* Is the field required?
*
* @return a boolean that says if the field is required
*/
public boolean isRequired() {
return isRequired;
}
/**
* Sets the fields required field
*
* @param required Is the field required?
*/
public void setRequired(boolean required) {
isRequired = required;
}
}

View File

@ -0,0 +1,33 @@
package xyz.sheepstar.util.console;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.event.console.ConsoleMessageReceivedEvent;
import java.util.Scanner;
public class ConsoleListenerThread extends Thread {
private final SheepstarImpl api;
private final Scanner scanner = new Scanner(System.in);
/**
* Basic constructor of the console listener thread
*
* @param api The sheepstar instance
*/
public ConsoleListenerThread(SheepstarImpl api) {
super("ConsoleListenerThread");
api.getEventManager().addEventListener(new ConsoleMessageReceivedListener());
this.api = api;
}
/**
* Runs an ConsoleMessageReceivedEvent as soon as a message has been sent
*/
@Override
public void run() {
while (true) {
new ConsoleMessageReceivedEvent(api, scanner.nextLine()).call();
}
}
}

View File

@ -0,0 +1,96 @@
package xyz.sheepstar.util.console;
import org.slf4j.Logger;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.bot.command.GuildCommand;
import xyz.sheepstar.util.log.LogManager;
import java.util.ArrayList;
import java.util.Arrays;
public class ConsoleManager {
private final Logger LOG = LogManager.getLog(ConsoleManager.class);
private final ArrayList<ConsoleCommand> REGISTERED_COMMANDS = new ArrayList<>();
private final SheepstarImpl api;
private final ConsoleListenerThread listenerThread;
/**
* Basic constructor of the console manager
*
* @param api The sheepstar instance
*/
public ConsoleManager(SheepstarImpl api) {
this.api = api;
listenerThread = new ConsoleListenerThread(api);
listenerThread.start();
registerDefaultCommands();
}
/**
* Registers all the default commands provided by the system / api
*/
private void registerDefaultCommands() {
}
/**
* Registers a console command
*
* @param command The command you want to register
*/
public void register(ConsoleCommand... command) {
REGISTERED_COMMANDS.addAll(Arrays.asList(command));
}
/**
* Runs when the user executes an command
*
* @param command The command
*/
public void run(String command) {
for (ConsoleCommand current : REGISTERED_COMMANDS) {
if (isValidCommand(command, current)) {
current.run(getArgs(command));
return;
}
}
LOG.error("Command not found");
}
/**
* Validates the command
*
* @param commandText The text you want to validate
* @param command The command you want to check
* @return an boolean that says if the command is valid
*/
private boolean isValidCommand(String commandText, ConsoleCommand command) {
String lowerText = commandText.toLowerCase();
if (lowerText.contains(" ")) lowerText = lowerText.substring(0, lowerText.indexOf(" "));
if (lowerText.contains("\n")) lowerText.substring(0, lowerText.indexOf("\n"));
return command.getAlias().contains(lowerText);
}
/**
* Get the arguments from an String
*
* @param message The string you want to get the arguments from
* @return the list of arguments
*/
private String[] getArgs(String message) {
ArrayList<String> parts = GuildCommand.getPartsFromInput(message);
parts.remove(0);
return parts.toArray(new String[0]);
}
/**
* Gets the registered commands
*
* @return the registered commands
*/
public ArrayList<ConsoleCommand> getRegisteredCommands() {
return REGISTERED_COMMANDS;
}
}

View File

@ -0,0 +1,19 @@
package xyz.sheepstar.util.console;
import xyz.sheepstar.util.event.api.EventListener;
import xyz.sheepstar.util.event.api.Listener;
import xyz.sheepstar.util.event.console.ConsoleMessageReceivedEvent;
public class ConsoleMessageReceivedListener implements Listener {
/**
* Gets executes when a user writes a message in the console
*
* @param event The event that happens
*/
@EventListener
public void handle(ConsoleMessageReceivedEvent event) {
event.getAPI().getConsoleManager().run(event.getMessage());
}
}

View File

@ -0,0 +1,43 @@
package xyz.sheepstar.util.event;
import xyz.sheepstar.util.Sheepstar;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.event.api.EventData;
import java.util.ArrayList;
public class SheepstarEvent {
private final SheepstarImpl api;
/**
* The basic constructor of the event that happens <b>anytime a event has been called</b>
*
* @param api The sheepstar instance
*/
public SheepstarEvent(SheepstarImpl api) {
this.api = api;
}
/**
* Calls the event
*/
public void call() {
final ArrayList<EventData> eventList = api.getEventManager().getEvents(this.getClass());
if (eventList == null) return;
for (EventData data : eventList)
try {
data.method.invoke(data.object, this);
} catch (Exception ignored) {
}
}
/**
* Gets the sheepstar instance
*
* @return the sheepstar instance
*/
public Sheepstar getAPI() {
return api;
}
}

View File

@ -0,0 +1,21 @@
package xyz.sheepstar.util.event.api;
import java.lang.reflect.Method;
public class EventData {
public final Object object;
public final Method method;
/**
* The basic constructor of the EventData
*
* @param object The registered event object
* @param method The registered event method
*/
public EventData(Object object, Method method) {
this.object = object;
this.method = method;
}
}

View File

@ -0,0 +1,11 @@
package xyz.sheepstar.util.event.api;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface EventListener {
}

View File

@ -0,0 +1,93 @@
package xyz.sheepstar.util.event.api;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.event.SheepstarEvent;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class EventManager {
private final SheepstarImpl api;
private final Map<Class<? extends SheepstarEvent>, ArrayList<EventData>> REGISTERED_EVENTS = new HashMap<>();
/**
* The basic constructor of the event manager
*
* @param api The sheepstar instance
*/
public EventManager(SheepstarImpl api) {
this.api = api;
}
/**
* Checks if the method is valid (contains the EventListener annotation)
*
* @param method The method you want to check
* @return a boolean that says if the method is valid
*/
private boolean isValidMethod(final Method method) {
return method.getParameterTypes().length == 1 || method.isAnnotationPresent(EventListener.class);
}
/**
* Adds an event listener
*
* @param o The listener you want to add
*/
public void addEventListener(Listener o) {
for (final Method method : o.getClass().getMethods()) if (isValidMethod(method)) register(method, o);
}
/**
* Removes an event listener
*
* @param o The listener you want to add
*/
public void removeEventListener(Listener o) {
for (ArrayList<EventData> registeredEvents : REGISTERED_EVENTS.values())
for (int i = registeredEvents.size() - 1; i >= 0; i--)
if (registeredEvents.get(i).object.equals(o)) registeredEvents.remove(i);
cleanEventList();
}
/**
* Registers a method
*
* @param method The method you want to register
* @param o The listener you want to register
*/
private void register(final Method method, final Listener o) {
final Class<?> clazz = method.getParameterTypes()[0];
final EventData methodData = new EventData(o, method);
if (!methodData.method.isAccessible()) methodData.method.setAccessible(true);
if (REGISTERED_EVENTS.containsKey(clazz)) {
if (!REGISTERED_EVENTS.get(clazz).contains(methodData)) REGISTERED_EVENTS.get(clazz).add(methodData);
} else {
REGISTERED_EVENTS.put((Class<? extends SheepstarEvent>) clazz, new ArrayList<EventData>() {{
this.add(methodData);
}});
}
}
/**
* Gets a list of the events mapped to a class
*
* @param clazz A class which extends the SheepstarEvent
* @return The list of the events
*/
public ArrayList<EventData> getEvents(final Class<? extends SheepstarEvent> clazz) {
return REGISTERED_EVENTS.get(clazz);
}
/**
* Clears the event list
*/
private void cleanEventList() {
REGISTERED_EVENTS.entrySet().removeIf(classArrayListEntry -> classArrayListEntry.getValue().isEmpty());
}
}

View File

@ -0,0 +1,4 @@
package xyz.sheepstar.util.event.api;
public interface Listener {
}

View File

@ -0,0 +1,17 @@
package xyz.sheepstar.util.event.console;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.event.SheepstarEvent;
public class ConsoleEvent extends SheepstarEvent {
/**
* The basic constructor of the Console Event
*
* @param api The sheepstar instance
*/
public ConsoleEvent(SheepstarImpl api) {
super(api);
}
}

View File

@ -0,0 +1,29 @@
package xyz.sheepstar.util.event.console;
import xyz.sheepstar.util.SheepstarImpl;
public class ConsoleMessageReceivedEvent extends ConsoleEvent {
private final String message;
/**
* The basic constructor of the Console Event,
* it happens when a console message has been received
*
* @param api The sheepstar instance
* @param message The message of the received event
*/
public ConsoleMessageReceivedEvent(SheepstarImpl api, String message) {
super(api);
this.message = message;
}
/**
* Gets the message received
*
* @return the received message
*/
public String getMessage() {
return message;
}
}

View File

@ -0,0 +1,30 @@
package xyz.sheepstar.util.event.module;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.event.SheepstarEvent;
import xyz.sheepstar.util.module.Module;
public class ModuleEvent extends SheepstarEvent {
Module module;
/**
* The basic constructor of the ModuleEvent
*
* @param api The sheepstar instance
* @param module The module
*/
public ModuleEvent(SheepstarImpl api, Module module) {
super(api);
this.module = module;
}
/**
* Gets the module of the event
*
* @return the module
*/
public Module getModule() {
return module;
}
}

View File

@ -0,0 +1,18 @@
package xyz.sheepstar.util.event.module;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.module.Module;
public class ModuleLoadedEvent extends ModuleEvent {
/**
* The basic constructor of the event that happens when a module has been loaded
*
* @param api The sheepstar instance
* @param module The module
*/
public ModuleLoadedEvent(SheepstarImpl api, Module module) {
super(api, module);
}
}

View File

@ -0,0 +1,17 @@
package xyz.sheepstar.util.event.module;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.module.Module;
public class ModuleLoadingEvent extends ModuleEvent {
/**
* The basic constructor of the event that happens when a module is loading
*
* @param api The sheepstar instance
* @param module The module
*/
public ModuleLoadingEvent(SheepstarImpl api, Module module) {
super(api, module);
}
}

View File

@ -0,0 +1,100 @@
package xyz.sheepstar.util.http.client;
import static xyz.sheepstar.util.http.client.RequestMethod.*;
public class Endpoint {
private final RequestMethod method;
private final String path;
/**
* Constructor of the {@link Endpoint}
*
* @param method The request method
* @param path The path of the endpoint
*/
public Endpoint(RequestMethod method, String path) {
this.method = method;
this.path = path;
}
/**
* Gets the request method
*
* @return the request method
*/
public RequestMethod getMethod() {
return method;
}
/**
* Gets the path of the endpoint
*
* @return the path of the endpoint
*/
public String getPath() {
return path;
}
public static class ApiKey {
public final static Endpoint CREATE_KEY = new Endpoint(PUT, "apikey");
public final static Endpoint GET_KEY = new Endpoint(GET, "apikey/{api_key}");
public final static Endpoint DELETE_KEY = new Endpoint(DELETE, "apikey/{api_key}");
}
public static class Article {
public final static Endpoint CREATE_ARTICLE = new Endpoint(PUT, "article");
public final static Endpoint DELETE_ARTICLE = new Endpoint(DELETE, "article");
public final static Endpoint GET_ARTICLE = new Endpoint(GET, "article/{article_id}");
public final static Endpoint FIND_ARTICLE = new Endpoint(GET, "article/{module_name}/{article_id}");
public final static Endpoint LIST_ARTICLES = new Endpoint(GET, "article/{module_name}/list");
}
public static class Gift {
public final static Endpoint CREATE_GIFT = new Endpoint(PUT, "gift");
public final static Endpoint GET_GIFT = new Endpoint(GET, "gift/{gift_id}");
public final static Endpoint DELETE_GIFT = new Endpoint(DELETE, "gift/{gift_id}");
public final static Endpoint UPDATE_GIFT = new Endpoint(PATCH, "gift");
public final static Endpoint REDEEM_CODE = new Endpoint(POST, "gift/redeem");
}
public static class Link {
public final static Endpoint CREATE_LINK = new Endpoint(PUT, "link");
public final static Endpoint DELETE_LINK = new Endpoint(DELETE, "link/{code}");
public final static Endpoint GET_LINK = new Endpoint(GET, "link/{code}");
}
public static class Media {
public final static Endpoint UPLOAD_MEDIA = new Endpoint(PUT, "media");
public final static Endpoint DELETE_MEDIA = new Endpoint(DELETE, "media/{asset_id}");
public final static Endpoint GET_MEDIA = new Endpoint(GET, "media/{asset_id}");
}
public static class Shop {
public final static Endpoint GET_ITEMS = new Endpoint(GET, "shop");
public final static Endpoint OWNS_ITEM = new Endpoint(GET, "shop/owns");
public final static Endpoint DEACTIVATE_ITEM = new Endpoint(DELETE, "shop");
public final static Endpoint ACTIVATE_ITEM = new Endpoint(PUT, "shop");
}
public static class User {
public final static Endpoint GET_GUILDS = new Endpoint(GET, "user/guilds");
}
}

View File

@ -0,0 +1,26 @@
package xyz.sheepstar.util.http.client;
public class ErrorResponse extends Response {
private String message;
/**
* Constructor of the {@link ErrorResponse}
*
* @param response The response from the {@link Requester}
*/
public ErrorResponse(okhttp3.Response response) {
super(response);
if (response == null) return;
message = getData().getString("message");
}
/**
* Returns the error message
*
* @return the error message
*/
public String getMessage() {
return message;
}
}

View File

@ -0,0 +1,77 @@
package xyz.sheepstar.util.http.client;
import net.dv8tion.jda.api.utils.data.DataObject;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import xyz.sheepstar.util.http.client.internal.RestActionImpl;
import java.util.concurrent.CompletableFuture;
public class Request<T> {
private final Route route;
private final DataObject data;
private final CompletableFuture<? super T> onSuccess;
private final RestActionImpl<T> restAction;
/**
* Constructor of the {@link Request}
*
* @param route The route of the request
* @param data The data of the request
* @param onSuccess The {@link CompletableFuture} that will be completed when the request is successful
* @param restAction The {@link RestActionImpl} that will be executed
*/
public Request(Route route, DataObject data, CompletableFuture<? super T> onSuccess, RestActionImpl<T> restAction) {
this.route = route;
this.data = data;
this.onSuccess = onSuccess;
this.restAction = restAction;
}
/**
* Handles the successful response of the {@link Request}
*
* @param response The {@link okhttp3.Response} from the request
*/
public void handleSuccess(okhttp3.Response response) {
onSuccess.complete(restAction.handle(new Response(response)));
}
/**
* Handles the failure of the {@link Request}
*
* @param response The {@link okhttp3.Response} from the request
*/
public void handleError(okhttp3.Response response) {
onSuccess.complete(restAction.handle(new ErrorResponse(response)));
}
/**
* Gets the {@link Route} of the {@link Request}
*
* @return The {@link Route}
*/
public Route getRoute() {
return route;
}
/**
* Gets the data of the {@link Request}
*
* @return The {@link DataObject}
*/
public DataObject getData() {
return data;
}
/**
* Converts the {@link Request} to a {@link RequestBody}
*
* @return the {@link RequestBody}
*/
public RequestBody convertToBody() {
return data != null ? RequestBody.create(data.toJson(), MediaType.parse("application/json; charset=utf-8")) : null;
}
}

View File

@ -0,0 +1,11 @@
package xyz.sheepstar.util.http.client;
public enum RequestMethod {
GET,
POST,
PUT,
DELETE,
PATCH
}

View File

@ -0,0 +1,77 @@
package xyz.sheepstar.util.http.client;
import okhttp3.OkHttpClient;
import org.slf4j.Logger;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.log.LogManager;
import java.util.concurrent.TimeUnit;
public class Requester {
private static final Logger LOG = LogManager.getLog(Requester.class);
private static final String USER_AGENT = "SheepstarBot";
private final SheepstarImpl api;
private final OkHttpClient client = new OkHttpClient.Builder().connectTimeout(0, TimeUnit.SECONDS).readTimeout(0, TimeUnit.SECONDS).build();
/**
* Constructor of the {@link Requester}
*
* @param api The {@link SheepstarImpl} instance
*/
public Requester(SheepstarImpl api) {
this.api = api;
}
/**
* Send a request to the API
*
* @param request The request to send
* @param <T> The type of the response
*/
public <T> void request(Request<?> request) {
okhttp3.Request.Builder builder = new okhttp3.Request.Builder();
builder.url(api.getConfig().getApiUrl() + "/" + request.getRoute().getCompiledRoute());
builder.method(request.getRoute().getEndpoint().getMethod().toString(), request.convertToBody());
if (!api.getConfig().getApiKey().isEmpty())
builder.addHeader("Authorization", "Bearer " + api.getConfig().getApiKey());
builder.addHeader("User-Agent", USER_AGENT);
okhttp3.Request build = builder.build();
try {
int attempt = 0;
okhttp3.Response lastResponse;
do {
lastResponse = client.newCall(build).execute();
if (lastResponse.code() == 200)
break;
attempt++;
try {
Thread.sleep(50L * attempt);
} catch (Exception ignored) {
}
} while (attempt < 3 && lastResponse.code() != 200);
if (lastResponse.code() != 200) {
request.handleError(lastResponse);
lastResponse.close();
return;
}
request.handleSuccess(lastResponse);
} catch (Exception e) {
request.handleError(null);
LOG.error("Error while requesting: {}", e.getMessage());
}
}
}

View File

@ -0,0 +1,70 @@
package xyz.sheepstar.util.http.client;
import net.dv8tion.jda.api.utils.data.DataArray;
import net.dv8tion.jda.api.utils.data.DataObject;
import okhttp3.ResponseBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Response {
private static final Logger LOG = LoggerFactory.getLogger(Response.class);
private int code = 500;
private String body = "{}";
/**
* Constructor of the {@link Response}
*
* @param response The {@link okhttp3.Response}
*/
public Response(okhttp3.Response response) {
if (response == null) return;
code = response.code();
try {
ResponseBody body = response.body();
this.body = body.string();
body.close();
} catch (Exception e) {
LOG.error("Could not get response body: {}", e.getMessage());
}
response.close();
}
/**
* Gets the {@link DataObject}
*
* @return the {@link DataObject}
*/
public DataObject getData() {
return DataObject.fromJson(body);
}
/**
* Gets the {@link DataArray}
*
* @return The {@link DataArray}
*/
public DataArray getArray() {
return DataArray.fromJson(body);
}
/**
* Gets the HTTP status code
*
* @return the HTTP status code
*/
public int getCode() {
return code;
}
/**
* Gets the body of the response
*
* @return the body of the response
*/
public String getBody() {
return body;
}
}

View File

@ -0,0 +1,12 @@
package xyz.sheepstar.util.http.client;
public interface RestAction<T> {
/**
* Completes the action
*
* @return the result of the action
*/
T complete();
}

View File

@ -0,0 +1,94 @@
package xyz.sheepstar.util.http.client;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
public class Route {
private final HashMap<String, String> compiled_patterns = new HashMap<>();
private final Endpoint endpoint;
private final HashMap<String, Object> query_params = new HashMap<>();
/**
* Constructor of the {@link Route}
*
* @param endpoint The endpoint of the route
*/
public Route(Endpoint endpoint) {
this.endpoint = endpoint;
}
/**
* Adds a pattern to the route
*
* @param key The key of the pattern
* @param value The value of the pattern
* @return The route
*/
public Route compilePattern(String key, String value) {
compiled_patterns.put(key, value);
return this;
}
/**
* Adds a query parameter to the route
*
* @param key The key of the query parameter
* @param value The value of the query parameter
* @return The route
*/
public Route addQueryParam(String key, Object value) {
query_params.put(key, value);
return this;
}
/**
* Returns the endpoint of the route
*
* @return the endpoint
*/
public Endpoint getEndpoint() {
return endpoint;
}
/**
* Returns the compiled pattern of the route
*
* @return the compiled pattern
*/
public String getCompiledRoute() {
String compiled_route = endpoint.getPath();
try {
for (Map.Entry<String, String> entry : compiled_patterns.entrySet()) {
compiled_route = compiled_route.replace(String.format("{%s}", entry.getKey()),
URLEncoder.encode(entry.getValue(), "UTF-8"));
}
} catch (UnsupportedEncodingException ignored) {
}
compiled_route += "/" + compileQuery();
return compiled_route;
}
/**
* Get the compiled query of the route
*
* @return the compiled query
*/
private String compileQuery() {
StringBuilder query = new StringBuilder();
try {
for (Map.Entry<String, Object> entry : query_params.entrySet()) {
query.append(String.format("%s%s=%s", (query.length() == 0) ? "?" : "&", entry.getKey(),
URLEncoder.encode(entry.getValue().toString(), "UTF-8")));
}
} catch (UnsupportedEncodingException ignored) {
}
return query.toString();
}
}

View File

@ -0,0 +1,40 @@
package xyz.sheepstar.util.http.client.actions.internal.article;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.http.client.Endpoint;
import xyz.sheepstar.util.http.client.ErrorResponse;
import xyz.sheepstar.util.http.client.Response;
import xyz.sheepstar.util.http.client.Route;
import xyz.sheepstar.util.http.client.entities.Article;
import xyz.sheepstar.util.http.client.entities.internal.ArticleImpl;
import xyz.sheepstar.util.http.client.internal.RestActionImpl;
public class FindArticleInfoImpl extends RestActionImpl<Article> {
private final String moduleName;
private final String articleId;
/**
* Constructor of the {@link FindArticleInfoImpl}
*
* @param api the api of the bot
*/
public FindArticleInfoImpl(SheepstarImpl api, String moduleName, String articleId) {
super(api);
this.moduleName = moduleName;
this.articleId = articleId;
}
@Override
protected Route finalizeRoute() {
return new Route(Endpoint.Article.FIND_ARTICLE)
.compilePattern("module_name", moduleName)
.compilePattern("article_id", articleId);
}
@Override
public Article handle(Response response) {
if (response instanceof ErrorResponse) return null;
return ArticleImpl.from(response.getData());
}
}

View File

@ -0,0 +1,37 @@
package xyz.sheepstar.util.http.client.actions.internal.article;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.http.client.Endpoint;
import xyz.sheepstar.util.http.client.ErrorResponse;
import xyz.sheepstar.util.http.client.Response;
import xyz.sheepstar.util.http.client.Route;
import xyz.sheepstar.util.http.client.entities.Article;
import xyz.sheepstar.util.http.client.entities.internal.ArticleImpl;
import xyz.sheepstar.util.http.client.internal.RestActionImpl;
public class GetArticleInfoActionImpl extends RestActionImpl<Article> {
private final String articleId;
/**
* Constructor of the {@link RestActionImpl}
*
* @param api the api of the bot
*/
public GetArticleInfoActionImpl(SheepstarImpl api, String articleId) {
super(api);
this.articleId = articleId;
}
@Override
protected Route finalizeRoute() {
return new Route(Endpoint.Article.GET_ARTICLE)
.compilePattern("article_id", articleId);
}
@Override
public Article handle(Response response) {
if (response instanceof ErrorResponse) return null;
return ArticleImpl.from(response.getData());
}
}

View File

@ -0,0 +1,48 @@
package xyz.sheepstar.util.http.client.actions.internal.article;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.http.client.Endpoint;
import xyz.sheepstar.util.http.client.ErrorResponse;
import xyz.sheepstar.util.http.client.Response;
import xyz.sheepstar.util.http.client.Route;
import xyz.sheepstar.util.http.client.entities.Article;
import xyz.sheepstar.util.http.client.entities.internal.ArticleImpl;
import xyz.sheepstar.util.http.client.internal.RestActionImpl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class GetArticlesActionImpl extends RestActionImpl<List<Article>> {
private final String moduleName;
/**
* Constructor of the {@link RestActionImpl}
*
* @param api the api of the bot
* @param moduleName The name of the module
*/
public GetArticlesActionImpl(SheepstarImpl api, String moduleName) {
super(api);
this.moduleName = moduleName;
}
@Override
protected Route finalizeRoute() {
return new Route(Endpoint.Article.LIST_ARTICLES)
.compilePattern("module_name", moduleName);
}
@Override
public List<Article> handle(Response response) {
if (response instanceof ErrorResponse) return null;
List<Article> items = new ArrayList<>();
for (Object o : response.getArray()) {
items.add(ArticleImpl.from((HashMap<String, Object>) o));
}
return items;
}
}

View File

@ -0,0 +1,44 @@
package xyz.sheepstar.util.http.client.actions.internal.gift;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.http.client.Endpoint;
import xyz.sheepstar.util.http.client.ErrorResponse;
import xyz.sheepstar.util.http.client.Response;
import xyz.sheepstar.util.http.client.Route;
import xyz.sheepstar.util.http.client.entities.Gift;
import xyz.sheepstar.util.http.client.entities.internal.GiftImpl;
import xyz.sheepstar.util.http.client.internal.RestActionImpl;
import java.text.ParseException;
public class GiftInfoActionImpl extends RestActionImpl<Gift> {
private final String giftId;
/**
* Constructor of the {@link RestActionImpl}
*
* @param api the api of the bot
* @param giftId The id of the gift
*/
public GiftInfoActionImpl(SheepstarImpl api, String giftId) {
super(api);
this.giftId = giftId;
}
@Override
protected Route finalizeRoute() {
return new Route(Endpoint.Gift.GET_GIFT)
.compilePattern("gift_id", giftId);
}
@Override
public Gift handle(Response response) {
if (response instanceof ErrorResponse) return null;
try {
return GiftImpl.from(response.getData());
} catch (ParseException ignored) {
}
return null;
}
}

View File

@ -0,0 +1,42 @@
package xyz.sheepstar.util.http.client.actions.internal.gift;
import net.dv8tion.jda.api.utils.data.DataObject;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.http.client.Endpoint;
import xyz.sheepstar.util.http.client.Response;
import xyz.sheepstar.util.http.client.Route;
import xyz.sheepstar.util.http.client.internal.RestActionImpl;
public class RedeemGiftActionImpl extends RestActionImpl<Integer> {
private final String giftId;
private final String guildId;
/**
* Constructor of the {@link RedeemGiftActionImpl}
*
* @param api The api of the bot
* @param giftId The id of the gift
* @param guildId The id of the guild
*/
public RedeemGiftActionImpl(SheepstarImpl api, String giftId, String guildId) {
super(api);
this.giftId = giftId;
this.guildId = guildId;
}
@Override
protected DataObject finalizeBody() {
return DataObject.empty().put("giftID", giftId).put("guildID", guildId);
}
@Override
protected Route finalizeRoute() {
return new Route(Endpoint.Gift.REDEEM_CODE);
}
@Override
public Integer handle(Response response) {
return response.getCode();
}
}

View File

@ -0,0 +1,40 @@
package xyz.sheepstar.util.http.client.actions.internal.shop;
import net.dv8tion.jda.api.utils.data.DataObject;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.http.client.Endpoint;
import xyz.sheepstar.util.http.client.Response;
import xyz.sheepstar.util.http.client.Route;
import xyz.sheepstar.util.http.client.internal.RestActionImpl;
public class ActivateArticleActionImpl extends RestActionImpl<Integer> {
private final String articleId;
private final String guildId;
/**
* Constructor of the {@link ActivateArticleActionImpl}
*
* @param api the api of the bot
*/
public ActivateArticleActionImpl(SheepstarImpl api, String articleId, String guildId) {
super(api);
this.articleId = articleId;
this.guildId = guildId;
}
@Override
protected DataObject finalizeBody() {
return DataObject.empty().put("articleID", articleId).put("guildID", guildId);
}
@Override
protected Route finalizeRoute() {
return new Route(Endpoint.Shop.ACTIVATE_ITEM);
}
@Override
public Integer handle(Response response) {
return response.getCode();
}
}

View File

@ -0,0 +1,39 @@
package xyz.sheepstar.util.http.client.actions.internal.shop;
import xyz.sheepstar.util.SheepstarImpl;
import xyz.sheepstar.util.http.client.Endpoint;
import xyz.sheepstar.util.http.client.ErrorResponse;
import xyz.sheepstar.util.http.client.Response;
import xyz.sheepstar.util.http.client.Route;
import xyz.sheepstar.util.http.client.internal.RestActionImpl;
public class HasArticleActionImpl extends RestActionImpl<Boolean> {
private final String articleId;
private final String guildId;
/**
* Constructor of the {@link HasArticleActionImpl}
*
* @param api the api of the bot
*/
public HasArticleActionImpl(SheepstarImpl api, String articleID, String guildID) {
super(api);
this.articleId = articleID;
this.guildId = guildID;
}
@Override
protected Route finalizeRoute() {
return new Route(Endpoint.Shop.OWNS_ITEM)
.addQueryParam("articleID", articleId)
.addQueryParam("guildID", guildId);
}
@Override
public Boolean handle(Response response) {
if (response instanceof ErrorResponse) return null;
return Boolean.valueOf(response.getBody());
}
}

Some files were not shown because too many files have changed in this diff Show More