feat: wip fml

This commit is contained in:
Alyx D Batte 2025-12-09 19:13:31 -05:00
parent 4d8d68af70
commit fb5e9494ff
38 changed files with 778 additions and 468 deletions

View File

@ -1,28 +0,0 @@
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
name: Java CI with Gradle
on:
push:
branches:
- '**'
pull_request:
branches:
- '**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.16
uses: actions/setup-java@v1
with:
java-version: 1.16
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build

View File

@ -26,24 +26,18 @@ repositories {
}
dependencies {
implementation("net.dv8tion:JDA:5.0.1")
implementation("net.dv8tion:JDA:6.0.0")
implementation 'org.xerial:sqlite-jdbc:3.41.2.2'
implementation 'com.github.Kaaz:ConfigurationBuilder:0.4'
implementation 'org.javacord:javacord:3.8.0'
implementation 'com.vdurmont:emoji-java:5.1.1'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'ch.qos.logback:logback-classic:1.2.5'
implementation 'com.google.code.gson:gson:2.8.8'
implementation 'com.squareup.okhttp3:okhttp:4.9.2'
implementation 'ch.qos.logback:logback-classic:1.5.13'
implementation 'com.google.code.gson:gson:2.8.9'
implementation 'org.springframework.boot:spring-boot-starter-actuator:2.5.4'
implementation 'org.springframework.boot:spring-boot-starter-web:2.5.4'
testImplementation 'org.springframework.boot:spring-boot-starter-test:2.5.4'
implementation platform('com.google.cloud:libraries-bom:23.0.0')
implementation 'com.google.cloud:google-cloud-secretmanager'
testImplementation group: 'junit', name: 'junit', version: '4.12'
testImplementation group: 'junit', name: 'junit', version: '4.13.1'
}
mainClassName = 'dev.salmonllama.fsbot.Main'

View File

@ -4,18 +4,14 @@
package dev.salmonllama.fsbot;
import dev.salmonllama.fsbot.config.BotConfig;
// import dev.salmonllama.fsbot.config.SecretManager;
import dev.salmonllama.fsbot.database.FSDB;
import dev.salmonllama.fsbot.config.EnvManager;
import dev.salmonllama.fsbot.guthix.Guthix;
import dev.salmonllama.fsbot.interactions.ServerConfigInteraction;
import dev.salmonllama.fsbot.listeners.*;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.requests.GatewayIntent;
import org.javacord.api.DiscordApiBuilder;
import dev.salmonllama.fsbot.utilities.Constants;
import org.javacord.api.entity.intent.Intent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
@ -30,26 +26,15 @@ public class Main {
private final static Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
BotConfig.initConfig(Constants.BOT_FOLDER, false);
FSDB.init();
String token;
if (System.getenv("ENVIRONMENT") != null)
{
token = BotConfig.BOT_TOKEN_PROD;
// token = SecretManager.DISCORD_TOKEN_PROD.getPlainText();
}
else
{
token = BotConfig.BOT_TOKEN_DEV;
// token = SecretManager.DISCORD_TOKEN.getPlainText();
}
String token = EnvManager.BOT_TOKEN;
JDA jda = JDABuilder.createLight(token, EnumSet.noneOf(GatewayIntent.class))
.addEventListeners(new ImageListener())
.addEventListeners(new ServerConfigInteraction())
.build();
jda.upsertCommand(ServerConfigInteraction.ServerConfigCommand()).queue();
new DiscordApiBuilder().addIntents(Intent.MESSAGE_CONTENT).setToken(token).login().thenAccept(api -> {
@SuppressWarnings("unused")

View File

@ -5,7 +5,6 @@
package dev.salmonllama.fsbot.commands.developer;
import com.vdurmont.emoji.EmojiParser;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.database.controllers.GalleryController;
import dev.salmonllama.fsbot.database.models.GalleryChannel;
import dev.salmonllama.fsbot.guthix.*;

View File

@ -4,7 +4,6 @@
package dev.salmonllama.fsbot.commands.general;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.guthix.*;
import org.javacord.api.entity.channel.TextChannel;
import org.javacord.api.entity.message.embed.EmbedBuilder;

View File

@ -5,7 +5,6 @@
package dev.salmonllama.fsbot.commands.staff;
import com.vdurmont.emoji.EmojiParser;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.database.controllers.OutfitController;
import dev.salmonllama.fsbot.guthix.*;
import org.apache.logging.log4j.util.Strings;

View File

@ -5,7 +5,6 @@
package dev.salmonllama.fsbot.commands.staff;
import com.vdurmont.emoji.EmojiParser;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.database.controllers.OutfitController;
import dev.salmonllama.fsbot.guthix.*;
import org.javacord.api.entity.channel.TextChannel;

View File

@ -5,7 +5,6 @@
package dev.salmonllama.fsbot.commands.staff;
import com.vdurmont.emoji.EmojiParser;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.database.controllers.OutfitController;
import dev.salmonllama.fsbot.guthix.*;
import org.javacord.api.entity.channel.TextChannel;

View File

@ -5,7 +5,6 @@
package dev.salmonllama.fsbot.commands.staff;
import com.vdurmont.emoji.EmojiParser;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.database.controllers.OutfitController;
import dev.salmonllama.fsbot.database.models.Outfit;
import dev.salmonllama.fsbot.guthix.*;

View File

@ -1,109 +0,0 @@
/*
* Copyright (c) 2021 Aleksei Gryczewski
*/
package dev.salmonllama.fsbot.commands.staff;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.database.controllers.ServerConfigController;
import dev.salmonllama.fsbot.database.models.ServerConfig;
import dev.salmonllama.fsbot.guthix.*;
import org.javacord.api.entity.message.embed.EmbedBuilder;
import org.javacord.api.util.logging.ExceptionLogger;
import java.util.Arrays;
import java.util.List;
public class WelcomeMessageCommand extends Command {
@Override public String name() { return "Welcome Message"; }
@Override public String description() { return "View or update the server welcome message. Options: get|set|getchannel|setchannel."; }
@Override public String usage() { return "welcomemessage <String opt> [String newMessage]"; }
@Override public CommandCategory category() { return CommandCategory.STAFF; }
@Override public CommandPermission permission() { return new CommandPermission(PermissionType.STATIC, "staff"); }
@Override public List<String> aliases() { return Arrays.asList("welcomemessage", "wmsg"); }
@Override
public void onCommand(CommandContext ctx) {
if (ctx.isPrivateMessage()) {
ctx.reply("This command can only be used within a server");
return;
}
if (ctx.getArgs().length < 1) {
ctx.reply("You need to supply arguments for this command");
return;
}
String[] args = ctx.getArgs();
switch (args[0]) {
case "get":
get(ctx);
break;
case "set": // TODO: check for args here
String newMsg = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
set(ctx, newMsg);
break;
default:
ctx.reply("You used this command incorrectly.");
}
}
private void get(CommandContext ctx) {
ctx.getServer().ifPresent( // If server is present (not private message) get the server config
server -> ServerConfigController.get(server.getIdAsString()).thenAcceptAsync(
possibleConf -> possibleConf.ifPresentOrElse( // Check for current server config
conf -> ctx.reply(getMsg(conf)), // Fetch and send the current welcome message
() -> ctx.reply(notFound()) // No welcome message exists, sorrynotsorry
)
));
}
private EmbedBuilder getMsg(ServerConfig config) {
return new EmbedBuilder()
.setTitle("Current Welcome Message")
.setDescription(config.getWelcomeMessage());
}
private EmbedBuilder notFound() {
return new EmbedBuilder()
.setTitle("Does not exist!")
.setDescription("No welcome message was found! use `~wmsg set` to set one!");
}
private void set(CommandContext ctx, String newMsg) {
ctx.getServer().ifPresent( // If server is present (private msg check) get the server's config
server -> ServerConfigController.get(server.getIdAsString()).thenAcceptAsync( // Check for a current server config
possibleConf -> possibleConf.ifPresentOrElse(
conf -> ctx.reply(updateMsg(conf, newMsg)), // Config exists, update with new welcome message
() -> ctx.reply(setNewMsg(server.getIdAsString(), newMsg))))); // Config does not exist, init and add new welcome message
}
private EmbedBuilder updateMsg(ServerConfig conf, String newMsg) {
// Updates a welcome message from an already existing server config
ServerConfig config = new ServerConfig.ServerConfigBuilder().from(conf)
.setWelcomeMessage(newMsg)
.build();
ServerConfigController.update(config).exceptionally(ExceptionLogger.get()); // TODO: Write a discord Throwable consumer like this
return new EmbedBuilder()
.setTitle("Welcome Message Set")
.addField("New Welcome Message:", config.getWelcomeMessage());
}
private EmbedBuilder setNewMsg(String serverId, String newMsg) {
// Creates a new server config and adds a welcome message
ServerConfig config = new ServerConfig.ServerConfigBuilder()
.setId(serverId)
.setPrefix(BotConfig.DEFAULT_PREFIX)
.setWelcomeMessage(newMsg)
.build();
ServerConfigController.insert(config);
return new EmbedBuilder()
.setTitle("Welcome Message Set!")
.setDescription("server conf has been created")
.addField("New Welcome Message:", newMsg);
}
}

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 2021 Aleksei Gryczewski
*/
// Shoutout to Kaaz (again) for a kickass config service: https://github.com/Kaaz/ConfigurationBuilder
package dev.salmonllama.fsbot.config;
import com.kaaz.configuration.ConfigurationBuilder;
import com.kaaz.configuration.ConfigurationOption;
import dev.salmonllama.fsbot.utilities.Constants;
import java.nio.file.Path;
import java.nio.file.Paths;
public class BotConfig {
@ConfigurationOption
public static String DB_ADDR = "SQLite connection address here";
@ConfigurationOption
public static String DB_NAME = "SQLite database name here";
@ConfigurationOption
public static String DEFAULT_PREFIX = "default prefix here";
@ConfigurationOption
public static String BOT_OWNER = "owner's id here";
@ConfigurationOption
public static String STAFF_ROLE = "staff role id here";
@ConfigurationOption
public static String REPORT_CHANNEL = "report channel";
@ConfigurationOption
public static String ACHIEVEMENT_CHANNEL = "achievement channel here";
@ConfigurationOption
public static String ANNOUNCEMENT_CHANNEL = "announcement channel here";
@ConfigurationOption
public static String NEWS_CHANNEL = "news channel here";
@ConfigurationOption
public static String VOTE_CHANNEL = "vote channel here";
@ConfigurationOption
public static String WELCOME_CHANNEL = "welcome channel here";
@ConfigurationOption
public static String JOIN_LOG = "join log channel";
@ConfigurationOption
public static String REPORT_LOG = "report_log_channel";
@ConfigurationOption
public static String OUTFIT_LOG = "outfit log channel";
@ConfigurationOption
public static String CONTEST_LOG = "zammy log here";
@ConfigurationOption
public static String ACTIVITY_LOG = "bot_log_channel";
@ConfigurationOption
public static String HYDRIX_ROLE = "hydrix role id here";
@ConfigurationOption
public static String MEMBER_ROLE = "member role id here";
@ConfigurationOption
public static String DEFAULT_REACTION = ":heartpulse:";
@ConfigurationOption
public static String HOME_SERVER = "Home server here";
@ConfigurationOption
public static String BOT_TOKEN_DEV = "bot token here";
@ConfigurationOption
public static String BOT_TOKEN_PROD = "production token here";
@ConfigurationOption
public static String IMGUR_BEARER = "Bearer token here";
@ConfigurationOption
public static String IMGUR_CLIENT = "client ID here";
public static void initConfig(Path filePath, boolean cleanfile) {
try {
new ConfigurationBuilder(BotConfig.class, Paths.get(filePath.toString(), Constants.CONFIG_NAME) .toFile()).build(cleanfile);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}

View File

@ -0,0 +1,16 @@
package dev.salmonllama.fsbot.config;
public class EnvManager {
// Bot configuration
public static String BOT_TOKEN = System.getenv("BOT_TOKEN");
public static String BOT_OWNER = System.getenv("BOT_OWNER");
public static String DEFAULT_COMMAND_PREFIX = System.getenv("DEFAULT_COMMAND_PREFIX");
public static String DEFAULT_IMAGE_REACTION = System.getenv(":heartpulse:");
// Internal API configurations
public static String API_URI = System.getenv("API_URI");
// External API configurations
public static String IMGUR_CLIENT_ID = System.getenv("IMGUR_CLIENT_ID");
public static String IMGUR_BEARER_TOKEN = System.getenv("IMGUR_BEARER_TOKEN");
}

View File

@ -1,33 +0,0 @@
/*
* Copyright (c) 2021 Aleksei Gryczewski
*/
package dev.salmonllama.fsbot.config;
import java.io.IOException;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
public enum SecretManager {
DISCORD_TOKEN ("projects/fashionscapers-212707/secrets/fs_discord_token/versions/latest"),
DISCORD_TOKEN_PROD ("projects/fashionscapers-212707/secrets/fs_discord_token_prod/versions/latest"),
IMGUR_ID ("projects/fashionscapers-212707/secrets/fs_imgur_client_id/versions/latest"),
IMGUR_BEARER ("projects/fashionscapers-212707/secrets/fs_imgur_bearer_token/versions/latest")
;
private final String resourceId;
SecretManager(String resourceId) {
this.resourceId = resourceId;
}
public String getPlainText() {
try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
return client.accessSecretVersion(this.resourceId).getPayload().getData().toStringUtf8();
} catch (IOException e) {
e.printStackTrace(); // TODO: Add plain text error message to log to console
System.exit(1); // Secrets are integral to full operation, crash if not retrieved properly.
return null;
}
}
}

View File

@ -6,7 +6,6 @@
package dev.salmonllama.fsbot.database;
import dev.salmonllama.fsbot.exceptions.UnknownParameterException;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.utilities.Constants;
import org.slf4j.Logger;

View File

@ -5,7 +5,6 @@
// Heavily inspired by Kaaz's Emily database connection: https://github.com/Kaaz/DiscordBot/tree/master/src/main/java/emily/db
package dev.salmonllama.fsbot.database;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.database.models.*;
import java.sql.SQLException;

View File

@ -0,0 +1,143 @@
package dev.salmonllama.fsbot.endpoints;
import com.google.gson.Gson;
import io.micrometer.core.lang.Nullable;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
public class ApiConnection {
private final HttpUrl REQUEST_URI;
private final HashMap<String, String> HEADERS;
private final Logger logger = LoggerFactory.getLogger(ApiConnection.class);
public ApiConnection(String uri, @Nullable HashMap<String, String> headers) {
this.REQUEST_URI = Objects.requireNonNull(HttpUrl.parse(uri));
this.HEADERS = headers;
}
public ApiConnection(String uri) {
this(uri, null);
}
public CompletableFuture<Response> get(@Nullable HashMap<String, String> parameters) {
HttpUrl.Builder urlBuilder = REQUEST_URI.newBuilder();
if (parameters != null) {
parameters.forEach(urlBuilder::addQueryParameter);
}
Request.Builder request = new Request.Builder()
.get()
.url(urlBuilder.build());
return call(request);
}
public CompletableFuture<Response> get() {
return get(null);
}
public CompletableFuture<Response> post(@Nullable HashMap<String, String> parameters, RequestBody body) {
HttpUrl.Builder urlBuilder = REQUEST_URI.newBuilder();
if (parameters != null) {
parameters.forEach(urlBuilder::addQueryParameter);
}
Request.Builder request = new Request.Builder()
.post(body)
.url(urlBuilder.build());
return call (request);
}
public CompletableFuture<Response> post(RequestBody body) {
return post(null, body);
}
public CompletableFuture<Response> put(@Nullable HashMap<String, String> parameters, RequestBody body) {
HttpUrl.Builder urlBuilder = REQUEST_URI.newBuilder();
if (parameters != null) {
parameters.forEach(urlBuilder::addQueryParameter);
}
Request.Builder request = new Request.Builder()
.put(body)
.url(urlBuilder.build());
return call(request);
}
public CompletableFuture<Response> put(RequestBody body) {
return put(null, body);
}
public CompletableFuture<Response> delete(@Nullable HashMap<String, String> parameters, @Nullable RequestBody body) {
HttpUrl.Builder urlBuilder = REQUEST_URI.newBuilder();
if (parameters != null) {
parameters.forEach(urlBuilder::addQueryParameter);
}
Request.Builder request = new Request.Builder()
.url(urlBuilder.build());
if (body != null) {
request.delete(body);
} else {
request.delete();
}
return call(request);
}
public CompletableFuture<Response> delete(RequestBody body) {
return delete(null, body);
}
public CompletableFuture<Response> delete(HashMap<String, String> parameters) {
return delete(parameters, null);
}
public CompletableFuture<Response> delete() {
return delete(null, null);
}
private CompletableFuture<Response> call(Request.Builder request) {
if (HEADERS != null) {
HEADERS.forEach(request::addHeader);
}
OkHttpClient client = new OkHttpClient().newBuilder().build();
return CompletableFuture.supplyAsync(() -> {
try (var response = client.newCall(request.build()).execute()) {
return response;
} catch (IOException e) {
throw new CompletionException(e);
}
});
}
public static <T> T unmarshall(ResponseBody body, Class<T> classOfT) throws IOException {
Gson gson = new Gson();
return gson.fromJson(body.string(), classOfT);
}
public static <T> T unmarshall(ResponseBody body, Type typeOfT) throws IOException {
Gson gson = new Gson();
return gson.fromJson(body.string(), typeOfT);
}
public static RequestBody marshall(Object obj) {
Gson gson = new Gson();
return RequestBody.create(gson.toJson(obj), MediaType.parse("application/json"));
}
}

View File

@ -0,0 +1,29 @@
package dev.salmonllama.fsbot.endpoints.fashionscape;
import dev.salmonllama.fsbot.endpoints.fashionscape.controllers.GalleryApi;
import dev.salmonllama.fsbot.endpoints.fashionscape.controllers.GuildConfigApi;
import dev.salmonllama.fsbot.endpoints.fashionscape.controllers.ImageApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FashionscapeApi {
public FashionscapeApi() {
}
@Bean
public static GuildConfigApi guildConfig() {
return new GuildConfigApi();
}
@Bean
public static ImageApi image() {
return new ImageApi();
}
@Bean
public static GalleryApi gallery() {
return new GalleryApi();
}
}

View File

@ -0,0 +1,44 @@
package dev.salmonllama.fsbot.endpoints.fashionscape.controllers;
import com.google.gson.reflect.TypeToken;
import dev.salmonllama.fsbot.config.EnvManager;
import dev.salmonllama.fsbot.endpoints.ApiConnection;
import dev.salmonllama.fsbot.endpoints.fashionscape.models.Gallery;
import java.io.IOException;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
public class GalleryApi {
private final String GALLERY_URI = EnvManager.API_URI + "/gallery";
private final ApiConnection conn;
public GalleryApi() {
this.conn = new ApiConnection(GALLERY_URI);
}
public CompletableFuture<Set<Gallery>> getAll(String guildId) {
HashMap<String, String> params = new HashMap<>();
params.put("guildid", guildId);
return conn.get(params).thenApplyAsync(response -> {
if (response.body() == null) {
throw new CompletionException(new RuntimeException("No Response"));
}
try {
return ApiConnection.unmarshall(response.body(), new TypeToken<Set<Gallery>>(){}.getType());
} catch (IOException e) {
throw new CompletionException(e);
}
});
}
public void create(Gallery.Create gallery) {
}
}

View File

@ -1,7 +1,8 @@
package dev.salmonllama.fsbot.endpoints.fashionscape.guildconfig;
package dev.salmonllama.fsbot.endpoints.fashionscape.controllers;
import dev.salmonllama.fsbot.config.EnvManager;
import dev.salmonllama.fsbot.endpoints.ApiConnection;
import dev.salmonllama.fsbot.endpoints.fashionscape.models.GuildConfig;
import okhttp3.RequestBody;
import java.io.IOException;

View File

@ -0,0 +1,4 @@
package dev.salmonllama.fsbot.endpoints.fashionscape.controllers;
public class ImageApi {
}

View File

@ -0,0 +1,24 @@
package dev.salmonllama.fsbot.endpoints.fashionscape.models;
public class Gallery {
private String objectId;
private String guildId;
private String channelid;
private String tag;
private String reaction;
public Gallery() {
}
public static class Create {
private String guildId;
private String channelId;
private String tag;
private String reaction;
public Create() {
}
}
}

View File

@ -0,0 +1,175 @@
package dev.salmonllama.fsbot.endpoints.fashionscape.models;
import com.google.gson.annotations.SerializedName;
import java.util.Map;
import java.util.Set;
public class GuildConfig {
public GuildConfig() {
}
//* General settings */
@SerializedName("object_id")
private String objectId;
@SerializedName("guild_id")
private String guildId;
@SerializedName("prefix")
private String prefix;
//* Reporting Module */
@SerializedName("report_enabled")
private boolean isReportingEnabled;
@SerializedName("report_persistent")
private boolean isReportLogPersistent;
@SerializedName("report_channel")
private String reportingStaffChannel;
//* Welcome Messaging Module */
@SerializedName("welcome_enabled")
private boolean isWelcomeEnabled;
@SerializedName("welcome_channel")
private String welcomeChannel;
@SerializedName("welcome_message")
private String welcomeMessage;
//* Social Reactions Module */
@SerializedName("social_enabled")
private boolean isSocialReactEnabled;
@SerializedName("social_channels")
private Set<String> socialReactChannels;
//* Celebrations Module */
@SerializedName("celebration_enabled")
private boolean isCelebrationEnabled;
@SerializedName("celebration_data")
private Map<String, String> celebrationData; //* <k, v> <channel_id, celebrate_emoji> */
//* Gallery Module */
@SerializedName("gallery_enabled")
private boolean isGalleryEnabled;
@SerializedName("gallery_channels")
private Set<String> galleryChannels; //* Gallery data will be stored in a diff table */
public String getObjectId() {
return objectId;
}
public void setObjectId(String objectId) {
this.objectId = objectId;
}
public String getGuildId() {
return guildId;
}
public void setGuildId(String guildId) {
this.guildId = guildId;
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public boolean isReportingEnabled() {
return isReportingEnabled;
}
public void setReportingEnabled(boolean reportingEnabled) {
isReportingEnabled = reportingEnabled;
}
public boolean isReportLogPersistent() {
return isReportLogPersistent;
}
public void setReportLogPersistent(boolean reportLogPersistent) {
isReportLogPersistent = reportLogPersistent;
}
public String getReportingStaffChannel() {
return reportingStaffChannel;
}
public void setReportingStaffChannel(String reportingStaffChannel) {
this.reportingStaffChannel = reportingStaffChannel;
}
public boolean isWelcomeEnabled() {
return isWelcomeEnabled;
}
public void setWelcomeEnabled(boolean welcomeEnabled) {
isWelcomeEnabled = welcomeEnabled;
}
public String getWelcomeChannel() {
return welcomeChannel;
}
public void setWelcomeChannel(String welcomeChannel) {
this.welcomeChannel = welcomeChannel;
}
public String getWelcomeMessage() {
return welcomeMessage;
}
public void setWelcomeMessage(String welcomeMessage) {
this.welcomeMessage = welcomeMessage;
}
public boolean isSocialReactEnabled() {
return isSocialReactEnabled;
}
public void setSocialReactEnabled(boolean socialReactEnabled) {
isSocialReactEnabled = socialReactEnabled;
}
public Set<String> getSocialReactChannels() {
return socialReactChannels;
}
public void setSocialReactChannels(Set<String> socialReactChannels) {
this.socialReactChannels = socialReactChannels;
}
public boolean isCelebrationEnabled() {
return isCelebrationEnabled;
}
public void setCelebrationEnabled(boolean celebrationEnabled) {
isCelebrationEnabled = celebrationEnabled;
}
public Map<String, String> getCelebrationData() {
return celebrationData;
}
public void setCelebrationData(Map<String, String> celebrationData) {
this.celebrationData = celebrationData;
}
public boolean isGalleryEnabled() {
return isGalleryEnabled;
}
public void setGalleryEnabled(boolean galleryEnabled) {
isGalleryEnabled = galleryEnabled;
}
public Set<String> getGalleryChannels() {
return galleryChannels;
}
public void setGalleryChannels(Set<String> galleryChannels) {
this.galleryChannels = galleryChannels;
}
}

View File

@ -0,0 +1,4 @@
package dev.salmonllama.fsbot.endpoints.fashionscape.models;
public class Image {
}

View File

@ -5,11 +5,10 @@
package dev.salmonllama.fsbot.endpoints.imgur;
//import dev.salmonllama.fsbot.config.SecretManager;
import dev.salmonllama.fsbot.config.EnvManager;
import okhttp3.*;
import org.json.JSONObject;
import dev.salmonllama.fsbot.config.BotConfig;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
@ -24,8 +23,8 @@ public class ImgurAPIConnection {
private final Request.Builder requestBuilder;
public ImgurAPIConnection() {
CLIENT_ID = BotConfig.IMGUR_CLIENT;
BEARER_TOKEN = BotConfig.IMGUR_BEARER;
CLIENT_ID = EnvManager.IMGUR_CLIENT_ID;
BEARER_TOKEN = EnvManager.IMGUR_BEARER_TOKEN;
// CLIENT_ID = SecretManager.IMGUR_ID.getPlainText();
// BEARER_TOKEN = SecretManager.IMGUR_BEARER.getPlainText();

View File

@ -4,62 +4,61 @@
package dev.salmonllama.fsbot.guthix;
import org.javacord.api.DiscordApi;
import org.javacord.api.entity.channel.TextChannel;
import org.javacord.api.entity.message.Message;
import org.javacord.api.entity.message.MessageAuthor;
import org.javacord.api.entity.message.embed.EmbedBuilder;
import org.javacord.api.entity.permission.Role;
import org.javacord.api.entity.server.Server;
import org.javacord.api.entity.user.User;
import dev.salmonllama.fsbot.config.BotConfig;
import org.javacord.api.event.message.MessageCreateEvent;
import dev.salmonllama.fsbot.config.EnvManager;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
public class CommandContext {
private MessageCreateEvent event;
private DiscordApi api;
private Message message;
private MessageAuthor author;
private TextChannel channel;
private Optional<Server> server;
private Command usedCommand;
private String usedAlias;
private String[] args;
private final MessageReceivedEvent event;
private final JDA jda;
private final Message message;
private final User author;
private final Channel channel;
private final Guild guild;
private final Command usedCommand;
private final String usedAlias;
private final String[] args;
private CommandContext(CommandContextBuilder builder) {
this.event = builder.event;
this.api = builder.api;
this.jda = builder.jda;
this.message = builder.message;
this.author = builder.author;
this.channel = builder.channel;
this.server = builder.server;
this.guild = builder.guild;
this.usedCommand = builder.usedCommand;
this.usedAlias = builder.usedAlias;
this.args = builder.args;
}
public DiscordApi getApi() {
return api;
public JDA getJDA() {
return jda;
}
public Message getMessage() {
return message;
}
public MessageAuthor getAuthor() {
public User getAuthor() {
return author;
}
public TextChannel getChannel() {
public Channel getChannel() {
return channel;
}
public Optional<Server> getServer() {
return server;
public Guild getGuild() {
return guild;
}
public Command getUsedCommand() {
@ -75,32 +74,19 @@ public class CommandContext {
}
public User getUser() {
if (author.asUser().isPresent()) {
return author.asUser().get();
} else {
// Log something to discord, I dunno
}
return null;
}
public Optional<Collection<Role>> getUserRoles() {
User user = getUser();
if (getServer().isPresent()) {
return Optional.of(user.getRoles(getServer().get()));
}
return Optional.empty();
return author;
}
public boolean isUserOwner() {
return getUser().getIdAsString().equals(BotConfig.BOT_OWNER);
return author.getId().equals(EnvManager.BOT_OWNER);
}
public boolean isPrivateMessage() {
return event.isPrivateMessage();
return !event.isFromGuild();
}
public CompletableFuture<Message> reply(String msg) {
return channel.sendMessage(msg);
return guild.getTextChannelById(channel.getId()).se
}
public CompletableFuture<Message> reply(EmbedBuilder embed) {
@ -116,28 +102,28 @@ public class CommandContext {
}
public static class CommandContextBuilder {
private MessageCreateEvent event;
private DiscordApi api;
private Message message;
private MessageAuthor author;
private TextChannel channel;
private Optional<Server> server;
private Command usedCommand;
private String usedAlias;
private String[] args;
private final MessageReceivedEvent event;
private final JDA jda;
private final Message message;
private final User author;
private final Channel channel;
private final Guild guild;
private final Command usedCommand;
private final String usedAlias;
private final String[] args;
public CommandContextBuilder(
MessageCreateEvent event,
MessageReceivedEvent event,
Command usedCommand,
String usedAlias,
String[] args
) {
this.event = event;
this.api = event.getApi();
this.jda = event.getJDA();
this.message = event.getMessage();
this.author = event.getMessageAuthor();
this.author = event.getAuthor();
this.channel = event.getChannel();
this.server = event.getServer();
this.guild = event.getGuild();
this.usedCommand = usedCommand;
this.usedAlias = usedAlias;
this.args = args;

View File

@ -11,10 +11,10 @@ import dev.salmonllama.fsbot.commands.rs3search.*;
import dev.salmonllama.fsbot.commands.staff.OutfitInfoCommand;
import dev.salmonllama.fsbot.commands.staff.*;
import dev.salmonllama.fsbot.database.controllers.UserBlacklistController;
import org.javacord.api.DiscordApi;
import org.javacord.api.entity.message.MessageAuthor;
import org.javacord.api.event.message.MessageCreateEvent;
import org.javacord.api.listener.message.MessageCreateListener;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -24,18 +24,18 @@ import java.util.HashMap;
/*
* Guthix is Fashionscape Bot's command repository and dispatcher
*/
public class Guthix implements MessageCreateListener {
public class Guthix extends ListenerAdapter {
private final static Logger logger = LoggerFactory.getLogger(Guthix.class);
@SuppressWarnings("unused")
private final DiscordApi api;
private final JDA jda;
private final Registry registry;
private final PermissionManager manager;
public Guthix(DiscordApi api) {
this.api = api;
api.addMessageCreateListener(this);
public Guthix(JDA jda) {
this.jda = jda;
jda.addEventListener(this);
manager = new PermissionManager();
registry = new Registry();
@ -76,31 +76,6 @@ public class Guthix implements MessageCreateListener {
addCommand(new StatsCommand());
addCommand(new PrivacyCommand());
// Osrs Search Commands
addCommand(new OsrsSearchCommand());
addCommand(new OsrsHeadCommand());
addCommand(new OsrsBodyCommand());
addCommand(new OsrsHandCommand());
addCommand(new OsrsLegsCommand());
addCommand(new OsrsFeetCommand());
addCommand(new OsrsCapeCommand());
addCommand(new OsrsNeckCommand());
addCommand(new OsrsShieldCommand());
addCommand(new OsrsWeaponCommand());
// Rs3 Search Commands
addCommand(new Rs3SearchCommand());
addCommand(new Rs3HeadCommand());
addCommand(new Rs3BodyCommand());
addCommand(new Rs3NeckCommand());
addCommand(new Rs3HandCommand());
addCommand(new Rs3FeetCommand());
addCommand(new Rs3LegsCommand());
addCommand(new Rs3BackCommand());
addCommand(new Rs3MainhandCommand());
addCommand(new Rs3OffhandCommand());
addCommand(new Rs3TwohandedCommand());
logger.info("Command initialization complete!");
}
@ -117,8 +92,8 @@ public class Guthix implements MessageCreateListener {
}
@Override
public void onMessageCreate(MessageCreateEvent event) {
MessageAuthor author = event.getMessageAuthor();
public void onMessageReceived(MessageReceivedEvent event) {
User author = event.getAuthor();
if (manager.sourceIsValid(author)) {

View File

@ -6,10 +6,9 @@ package dev.salmonllama.fsbot.guthix;
import java.util.concurrent.atomic.AtomicBoolean;
import org.javacord.api.entity.message.MessageAuthor;
import dev.salmonllama.fsbot.database.controllers.StaticPermissionController;
import dev.salmonllama.fsbot.database.models.StaticPermission;
import net.dv8tion.jda.api.entities.User;
public class PermissionManager {
@ -23,9 +22,6 @@ public class PermissionManager {
switch (permType) {
case NONE:
return true;
case ROLE:
// If the author has the role, yes. Doesn't work in DM
return roleHandler(permValue, ctx);
case STATIC:
return staticHandler(permValue, ctx);
case PERMISSION:
@ -38,14 +34,6 @@ public class PermissionManager {
}
}
private boolean roleHandler(String roleId, CommandContext ctx) {
if (ctx.getUserRoles().isEmpty()) {
ctx.reply("This command can only be used in a server");
return false;
}
return ctx.getUserRoles().get().stream().anyMatch(role -> role.getIdAsString().equals(roleId));
}
private boolean ownerHandler(CommandContext ctx) {
return ctx.isUserOwner();
}
@ -71,7 +59,7 @@ public class PermissionManager {
return ret.get();
}
boolean sourceIsValid(MessageAuthor author) {
return !author.isBotUser() && !author.isWebhook();
boolean sourceIsValid(User author) {
return !author.isBot() && !author.isSystem();
}
}

View File

@ -4,8 +4,6 @@
package dev.salmonllama.fsbot.guthix;
import dev.salmonllama.fsbot.config.BotConfig;
import java.util.*;
import java.util.function.Predicate;

View File

@ -0,0 +1,134 @@
package dev.salmonllama.fsbot.interactions;
import dev.salmonllama.fsbot.endpoints.fashionscape.controllers.GuildConfigApi;
import dev.salmonllama.fsbot.internal.guildcfg.GuildConfigHelper;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Objects;
public class ServerConfigInteraction extends ListenerAdapter {
@Autowired
private GuildConfigHelper guildConfigHelper;
@Override
public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
if (!event.isFromGuild()) {
event.reply("This command can only be used inside a server").queue();
return;
}
if (event.getSubcommandGroup() != null) { //* There is a subcommand group */
if (event.getSubcommandGroup().equalsIgnoreCase("reports") && event.getSubcommandName() != null) { //* Process individual subcommands for Reporting Module
switch (event.getSubcommandName().toLowerCase()) {
case "enable":
guildConfigHelper.enableReports(
Objects.requireNonNull(event.getGuild()).getId(),
Objects.requireNonNull(event.getOption("channel", OptionMapping::getAsChannel)).getId(),
event.getOption("persist", OptionMapping::getAsBoolean) != null && event.getOption("persist", OptionMapping::getAsBoolean)
);
break;
case "disable":
guildConfigHelper.disableReports(
Objects.requireNonNull(event.getGuild()).getId()
);
break;
}
}
} else { //* No subcommand group, process default (display full config) */
event.deferReply().queue();
guildConfigHelper.getGuildConfig(Objects.requireNonNull(event.getGuild()).getId()).thenAcceptAsync(cfg -> {
event.reply(cfg.toString()).queue();
});
}
}
private static SubcommandData welcomeModuleSubCommand() {
return new SubcommandData("Welcome Messages", "Manage the welcome message module")
.addOption(OptionType.BOOLEAN, "Enabled", "Is the module enabled for this server?", true)
.addOption(OptionType.CHANNEL, "Channel", "Which channel should welcome messages be sent to?", true)
.addOption(OptionType.STRING, "Message", "What should the welcome message say?", true)
;
}
public static SlashCommandData ServerConfigCommand() {
return Commands.slash("config", "View the server's configuration")
.addSubcommandGroups(
new SocialReactModule(),
new ReportModule()
)
.setDefaultPermissions(DefaultMemberPermissions.enabledFor(
Permission.MANAGE_SERVER,
Permission.MODERATE_MEMBERS
))
;
}
private static class SocialReactModule extends SubcommandGroupData {
private SocialReactModule() {
super("Social", "Options related to Social Reacts");
this.addSubcommands(
enableSocialChannels(),
disableSocialChannels(),
addSocialChannel(),
removeSocialChannel()
);
}
private SubcommandData enableSocialChannels() {
return new SubcommandData("Enable", "Enable the social react module");
}
private SubcommandData disableSocialChannels() {
return new SubcommandData("Disable", "Disable the social react module");
}
private SubcommandData addSocialChannel() {
return new SubcommandData("Add", "Add a channel as a social channel")
.addOption(OptionType.CHANNEL, "Channel", "The channel that should have social reactions", true)
;
}
private SubcommandData removeSocialChannel() {
return new SubcommandData("Remove", "Remove a channel from the social react channel list")
.addOption(OptionType.CHANNEL, "Channel", "The channel that should no longer have social reactions", true)
;
// TODO: pre-populate this list with channels that are currently enabled.
}
}
private static class ReportModule extends SubcommandGroupData {
private ReportModule() {
super("Reports", "Options related to reporting module (modmail)");
this.addSubcommands(
enableReporting(),
disableReporting()
);
}
private SubcommandData enableReporting() {
return new SubcommandData("Enable", "Enable the reporting module")
.addOption(OptionType.CHANNEL, "Channel", "Where should reports be sent? This should be a moderator-only channel", true)
.addOption(OptionType.BOOLEAN, "Persist", "Should reporting logs be stored externally? (Default false)", false)
;
}
private SubcommandData disableReporting() {
return new SubcommandData("Disable", "Disable the reporting module");
}
}
}

View File

@ -0,0 +1,33 @@
package dev.salmonllama.fsbot.interactions.reporting;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
public class ReportModuleInteraction extends ListenerAdapter {
@Override
public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
if (event.getName().equals("reportmodule")) {
boolean enabled = event.getOption("enabled", OptionMapping::getAsBoolean);
Channel reportChannel = event.getOption("mod_channel", OptionMapping::getAsChannel);
boolean loggingEnabled = event.getOption("enable_logging", OptionMapping::getAsBoolean);
// Gather the data and send it to the api service
}
}
public static SlashCommandData ReportModuleCommand() {
return Commands.slash("reportmodule", "Manage the server's modmail reporting settings")
.addOption(OptionType.BOOLEAN, "enabled", "Whether the module should be enabled or disabled", true)
.addOption(OptionType.CHANNEL, "mod_channel", "The channel to send modmail reports to", true)
.addOption(OptionType.BOOLEAN, "enable_logging", "Whether modmail reports should be preserved in an external log", true)
.setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER, Permission.MODERATE_MEMBERS));
}
}

View File

@ -0,0 +1,97 @@
package dev.salmonllama.fsbot.internal.guildcfg;
import dev.salmonllama.fsbot.endpoints.fashionscape.controllers.GuildConfigApi;
import dev.salmonllama.fsbot.endpoints.fashionscape.models.GuildConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.yaml.snakeyaml.util.ArrayUtils;
import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@Configuration
public class GuildConfigHelper {
@Autowired
private GuildConfigApi guildConfigApi;
public GuildConfigHelper() {
}
@Bean
public GuildConfigHelper getGuildConfigHelperBean() {
return new GuildConfigHelper();
}
public CompletableFuture<GuildConfig> getGuildConfig(String guildId) {
return guildConfigApi.get(guildId);
}
public CompletableFuture<Void> setPrefix(String guildId, String prefix) {
return getGuildConfig(guildId).thenAcceptAsync(cfg -> {
cfg.setPrefix(prefix);
guildConfigApi.update(cfg);
});
}
public CompletableFuture<Void> enableReports(String guildId, String channelId, boolean shouldPersist) {
return getGuildConfig(guildId).thenAcceptAsync(cfg -> {
cfg.setReportingEnabled(true);
cfg.setReportingStaffChannel(channelId);
cfg.setReportLogPersistent(shouldPersist);
guildConfigApi.update(cfg);
});
}
public CompletableFuture<Void> disableReports(String guildId) {
return getGuildConfig(guildId).thenAcceptAsync(cfg -> {
cfg.setReportingEnabled(false);
guildConfigApi.update(cfg);
});
}
public CompletableFuture<Void> enableWelcomes(String guildId, String channelId, String msg) {
return getGuildConfig(guildId).thenAcceptAsync(cfg -> {
cfg.setWelcomeEnabled(true);
cfg.setWelcomeChannel(channelId);
cfg.setWelcomeMessage(msg);
guildConfigApi.update(cfg);
});
}
public CompletableFuture<Void> disableWelcomes(String guildId) {
return getGuildConfig(guildId).thenAcceptAsync(cfg -> {
cfg.setWelcomeEnabled(false);
guildConfigApi.update(cfg);
});
}
public CompletableFuture<Void> enableSocial(String guildId, String ...channelIds) {
return getGuildConfig(guildId).thenAcceptAsync(cfg -> {
cfg.setSocialReactEnabled(true);
cfg.setSocialReactChannels(Set.of(channelIds));
guildConfigApi.update(cfg);
});
}
public CompletableFuture<Void> disableSocial(String guildId) {
return getGuildConfig(guildId).thenAcceptAsync(cfg -> {
cfg.setSocialReactEnabled(false);
});
}
public CompletableFuture<Void> addSocialChannels(String guildId, String ...channelIds) {
return getGuildConfig(guildId).thenAcceptAsync(cfg -> {
cfg.setSocialReactChannels(Set.of(cfg.getSocialReactChannels(), channelIds));
})
}
}

View File

@ -5,7 +5,6 @@
package dev.salmonllama.fsbot.listeners;
import com.vdurmont.emoji.EmojiParser;
import dev.salmonllama.fsbot.config.BotConfig;
import org.javacord.api.entity.message.MessageAttachment;
import org.javacord.api.event.message.MessageCreateEvent;
import org.javacord.api.listener.message.MessageCreateListener;

View File

@ -4,7 +4,6 @@
package dev.salmonllama.fsbot.listeners;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.database.controllers.GalleryController;
import dev.salmonllama.fsbot.database.controllers.OutfitController;
import dev.salmonllama.fsbot.database.controllers.UserBlacklistController;
@ -116,45 +115,8 @@ public class ImageListener extends ListenerAdapter {
Outfit outfit = outfitBuilder.build();
OutfitController.insert(outfit).thenAcceptAsync((Void) -> {
// Log the outfit
// // TODO: START ZAMMY LOG
// if (outfit.getTag().equals("necro-contest"))
// {
// event.getJDA().getTextChannelById(BotConfig.CONTEST_LOG).ifPresentOrElse(chnl ->
// {
// EmbedBuilder response = new EmbedBuilder()
// .setTitle("Outfit Added")
// .setAuthor(event.getMessageAuthor())
// .setThumbnail(outfit.getLink())
// .setFooter(String.format("%s | %s", outfit.getTag(), outfit.getId()))
// .setUrl(outfit.getLink())
// .setColor(Color.GREEN)
// .addField("Uploaded:", outfit.getCreated().toString())
// .addField("Discord Name:", outfit.getDiscordName());
//
// if (!outfit.getMeta().equals("")) {
// response.addField("Meta:", outfit.getMeta());
// }
//
// chnl.sendMessage(response);
// logger.info(String.format("Outfit from %s successfully added to the running event.", event.getMessageAuthor().getDiscriminatedName()));
//
// // Add the reaction to the original message
// GalleryController.getEmoji(channel.getIdAsString()).thenAcceptAsync(
// emoji -> event.getMessage().addReaction(EmojiParser.parseToUnicode(emoji))
// ).exceptionally(ExceptionLogger.get());
// }, () ->
// {
// // Fallback error message to me
// event.getApi().getUserById(BotConfig.BOT_OWNER).thenAcceptAsync(
// user -> user.sendMessage("Could not find CONTEST_LOG")
// );
// });
// }
// // TODO: END ZAMMY LOG
var logChannel = event.getJDA().getTextChannelById(BotConfig.OUTFIT_LOG);
var logChannel = event.getJDA().getTextChannelById(BotConfig.OUTFIT_LOG); // TODO: Gallery channel configured log channel
if (logChannel != null) {
EmbedBuilder response = new EmbedBuilder()
.setTitle("Outfit Added")
@ -175,7 +137,7 @@ public class ImageListener extends ListenerAdapter {
// Add the emoji reaction to the message
GalleryController.getEmoji(eventChannel.getId()).thenAcceptAsync(
emoji -> event.getMessage().addReaction(Emoji.fromUnicode(emoji))
emoji -> event.getMessage().addReaction(Emoji.fromUnicode(emoji)).queue()
);
} else {
// TODO: Fallback error logging in owner DMs

View File

@ -4,7 +4,6 @@
package dev.salmonllama.fsbot.listeners;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.database.controllers.ServerConfigController;
import dev.salmonllama.fsbot.services.MemberRoleService;
import org.javacord.api.event.server.member.ServerMemberJoinEvent;

View File

@ -12,7 +12,6 @@ import org.javacord.api.entity.message.MessageAuthor;
import org.javacord.api.entity.message.embed.EmbedBuilder;
import org.javacord.api.event.message.MessageCreateEvent;
import org.javacord.api.listener.message.MessageCreateListener;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.utilities.MessageUtilities;
import java.awt.*;

View File

@ -5,7 +5,6 @@
package dev.salmonllama.fsbot.listeners;
import com.vdurmont.emoji.EmojiParser;
import dev.salmonllama.fsbot.config.BotConfig;
import org.javacord.api.event.message.MessageCreateEvent;
import org.javacord.api.listener.message.MessageCreateListener;

View File

@ -4,8 +4,6 @@
package dev.salmonllama.fsbot.services;
import dev.salmonllama.fsbot.config.BotConfig;
import org.javacord.api.event.server.member.ServerMemberJoinEvent;
public class MemberRoleService implements Runnable {

View File

@ -4,7 +4,6 @@
package dev.salmonllama.fsbot.utilities;
import dev.salmonllama.fsbot.config.BotConfig;
import dev.salmonllama.fsbot.guthix.CommandContext;
import org.javacord.api.entity.message.embed.EmbedBuilder;