Initial commit for handling forms

This commit is contained in:
Teriuihi 2024-03-31 11:02:51 +02:00
parent c7120cc26c
commit 964bfc85fa
13 changed files with 245 additions and 16 deletions

View File

@ -3,6 +3,7 @@ plugins {
id("java")
id("com.github.johnrengelman.shadow") version "7.1.0"
id("maven-publish")
id("org.springframework.boot") version("2.7.8")
}
group = "com.alttd"
@ -34,12 +35,16 @@ tasks {
withType<Jar> {
manifest {
attributes["Main-Class"] = "${rootProject.group}.${project.name}"
// attributes["Main-Class"] = "BOOT-INF/classes/${rootProject.group}.${project.name}"
attributes["Main-Class"] = "org.springframework.boot.loader.JarLauncher"
}
}
shadowJar {
archiveFileName.set(rootProject.name + ".jar")
manifest {
attributes["Main-Class"] = "org.springframework.boot.loader.JarLauncher"
}
}
build {
@ -70,4 +75,7 @@ dependencies {
compileOnly("org.projectlombok:lombok:1.18.30")
annotationProcessor("org.projectlombok:lombok:1.18.24")
implementation("com.alttd:AltitudeLogs:1.0")
implementation("org.springframework.boot:spring-boot-starter-web:3.2.1")
implementation("org.springframework.boot:spring-boot-starter-validation:3.2.1")
implementation("com.google.code.gson:gson:2.8.9")
}

View File

@ -7,28 +7,44 @@ import com.alttd.database.Database;
import com.alttd.database.DatabaseTables;
import com.alttd.listeners.JDAListener;
import com.alttd.util.Logger;
import lombok.Getter;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.requests.GatewayIntent;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Path;
@SpringBootApplication
public class AltitudeBot {
private JDA jda;
@Getter
private static AltitudeBot instance;
public static AltitudeBot getInstance() {
return instance;
}
private static String path;
public static void main(String[] args) {
if (args.length == 0) { //TODO change scripts so it works with this
System.out.println("Please give the location for the configs as an arg");
return;
}
path = args[0];
instance = new AltitudeBot();
instance.start();
instance.start(args);
// SpringApplication.run(AltitudeBot.class, args);
new SpringApplicationBuilder(AltitudeBot.class)
.web(WebApplicationType.SERVLET) // .REACTIVE, .SERVLET
.run(args);
}
private void start() {
private void start(String[] args) {
// Logger.altitudeLogs.info("Starting spring application");
// SpringApplication.run(AltitudeBot.class, args);
Logger.altitudeLogs.info("Starting bot...");
initConfigs();
jda = JDABuilder.createDefault(SettingsConfig.TOKEN,
@ -52,11 +68,11 @@ public class AltitudeBot {
// } catch (IllegalArgumentException e) {
// Logger.exception(e);
// }
initListeners();
initListeners(args);
}
private void initListeners() {
jda.addEventListener(new JDAListener(jda));
private void initListeners(String[] args) {
jda.addEventListener(new JDAListener(jda, args));
}
private void initConfigs() {
@ -67,7 +83,13 @@ public class AltitudeBot {
public String getDataFolder() {
try {
return new File(AltitudeBot.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getPath();
// return new File(AltitudeBot.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getPath();
File file = Path.of(new URI("file://"+ path)).toFile();
if (!file.exists() || !file.canWrite() || !file.isDirectory()) {
System.out.println("Directory does not exist or can't be written to: " + file.getPath());
return null;
}
return file.getPath();
} catch (URISyntaxException e) {
Logger.altitudeLogs.error("Unable to retrieve config directory");
e.printStackTrace();

View File

@ -142,8 +142,7 @@ public class CommandAuction extends DiscordCommand {
private void addScreenshot(Message.Attachment screenshot, Message message) {
String dataFolder = AltitudeBot.getInstance().getDataFolder();
Path parent = Path.of(dataFolder).getParent();
Path path = Path.of(parent.toString() + UUID.randomUUID() + "." + screenshot.getFileExtension());
Path path = Path.of(dataFolder + UUID.randomUUID() + "." + screenshot.getFileExtension());
screenshot.getProxy().downloadToFile(path.toFile()).whenComplete((file, throwable) ->
message.editMessageAttachments(AttachedFile.fromData(file)).queue(done -> file.delete(), failed -> {
Util.handleFailure(failed);

View File

@ -0,0 +1,52 @@
package com.alttd.communication.contact;
import com.alttd.AltitudeBot;
import com.alttd.communication.formData.ContactFormData;
import jakarta.validation.Valid;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.CompletableFuture;
@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/api/contact")
public class ContactEndpoint {
private static final Logger logger = LoggerFactory.getLogger(ContactEndpoint.class);
@PostMapping("/submitContactForm")
public CompletableFuture<ResponseEntity<String>> sendFormToDiscord(@Valid @RequestBody ContactFormData formData) {
logger.debug("Sending form to Discord: " + formData);
MessageEmbed messageEmbed = formData.toMessageEmbed();
Guild guild = AltitudeBot.getInstance().getJDA().getGuildById(514920774923059209L);
if (guild == null) {
logger.error("Unable to retrieve staff guild");
return CompletableFuture.completedFuture(ResponseEntity.internalServerError().body("Failed to submit form to Discord"));
}
TextChannel channel = guild.getChannelById(TextChannel.class, 514922567883292673L);
if (channel == null) {
logger.error("Unable to retrieve contact form channel");
return CompletableFuture.completedFuture(ResponseEntity.internalServerError().body("Failed to submit form to Discord"));
}
return CompletableFuture.supplyAsync(() -> {
try {
Message complete = channel.sendMessageEmbeds(messageEmbed).complete();
if (complete != null)
return ResponseEntity.ok("");
} catch (Exception exception) {
logger.error("Failed to send message to Discord", exception);
}
return ResponseEntity.internalServerError().body("Failed to submit form to Discord");
});
}
}

View File

@ -0,0 +1,51 @@
package com.alttd.communication.formData;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;
import org.hibernate.validator.constraints.Length;
import java.awt.*;
public class ContactFormData extends Form {
public ContactFormData(String username, String email, String question) {
this.username = username;
this.email = email;
this.question = question;
}
@NotEmpty(message = "You have to provide a username")
@Length(min = 3, max = 16, message = "Usernames have to be between 3 and 16 characters")
@Pattern(regexp = "[a-zA-Z-0-9_]{3,16}", message = "Your username has to be a valid Minecraft username")
public final String username;
@NotEmpty(message = "You have to provide an e-mail address")
@Email(regexp = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)])",
message = "This is not a valid e-mail address")
public final String email;
@Length(min = 11, max = 2000, message = "Your question should have between 10 and 2000 characters")
public final String question;
@Override
public String toString() {
return "ContactFormData{" +
"username='" + username + '\'' +
", email='" + email + '\'' +
", question='" + question + '\'' +
'}';
}
@Override
public MessageEmbed toMessageEmbed() {
return new EmbedBuilder()
.addField("Username", username, false)
.addField("email", email, false)
.appendDescription(question)
.setColor(Color.GREEN)
.build();
}
}

View File

@ -0,0 +1,11 @@
package com.alttd.communication.formData;
import net.dv8tion.jda.api.entities.MessageEmbed;
public abstract class Form {
@Override
public abstract String toString();
public abstract MessageEmbed toMessageEmbed();
}

View File

@ -27,7 +27,7 @@ public abstract class AbstractConfig {
private ConfigurationNode config;
protected AbstractConfig(String filename) {
init(new File(new File(AltitudeBot.getInstance().getDataFolder()).getParentFile(), filename), filename);
init(new File(new File(AltitudeBot.getInstance().getDataFolder()), filename), filename);
}
private void init(File file, String filename) {

View File

@ -176,6 +176,21 @@ public class DatabaseTables {
}
}
private void createSettingsTable() {
String sql = "CREATE TABLE IF NOT EXISTS settings(" +
"name VARCHAR(32) NOT NULL, " +
"value VARCHAR(64) NOT NULL, " +
"type VARCHAR(16) NOT NULL, " +
"PRIMARY KEY (name)" +
")";
try {
connection.prepareStatement(sql).executeUpdate();
} catch (SQLException e) {
Logger.altitudeLogs.error(e);
Logger.altitudeLogs.error("Unable to create auction settings table, shutting down...");
}
}
public static void createTables(Connection connection) {
if (instance == null)
instance = new DatabaseTables(connection);

View File

@ -0,0 +1,4 @@
package com.alttd.database.queries.settings;
public class QueriesSettings {
}

View File

@ -0,0 +1,59 @@
package com.alttd.database.queries.settings;
import com.alttd.database.Database;
import java.sql.*;
import java.util.List;
import java.util.stream.Collectors;
public class Setting {
private final List<Class> allowedClasses = List.of(Boolean.class, Integer.class, Long.class, Float.class, Double.class, String.class);
public <T> void insertSetting(String key, T value, String type) throws SQLException, IllegalArgumentException {
if (!allowedClasses.contains(type)) {
throw new IllegalArgumentException(String.format("Invalid type, the only allowed types are: %s", allowedClasses.stream().map(Class::getSimpleName).collect(Collectors.joining(", "))));
}
String query = "INSERT INTO settings (name, value, type) VALUES (?, ?, ?)";
try (Connection connection = DriverManager.getConnection("your_connection_string");
PreparedStatement preparedStatement = connection.prepareStatement(query)) {
preparedStatement.setString(1, key);
preparedStatement.setString(2, value.toString());
preparedStatement.setString(3, type);
preparedStatement.executeUpdate();
}
}
public <T> T getSetting(String key, Class<T> type) throws SQLException, IllegalArgumentException {
if (!allowedClasses.contains(type)) {
throw new IllegalArgumentException(String.format("Invalid type, the only allowed types are: %s", allowedClasses.stream().map(Class::getSimpleName).collect(Collectors.joining(", "))));
}
String query = "SELECT value, type FROM settings WHERE name = ?";
try (Connection connection = Database.getDatabase().getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query)) {
preparedStatement.setString(1, key);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
String dbType = resultSet.getString("type");
if (!dbType.equals(type.getSimpleName())) {
throw new IllegalArgumentException(String.format("%s is of type %s not %s", key, dbType, type.getSimpleName()));
}
String value = resultSet.getString("value");
if (type.equals(Integer.class)) {
return type.cast(Integer.parseInt(value));
} else if (type.equals(Boolean.class)) {
return type.cast(Boolean.parseBoolean(value));
} // and so on for other types
else {
return type.cast(value);
}
}
}
throw new SQLException("Key not found in settings");
}
}

View File

@ -1,5 +1,6 @@
package com.alttd.listeners;
import com.alttd.AltitudeBot;
import com.alttd.buttonManager.ButtonManager;
import com.alttd.commandManager.CommandManager;
import com.alttd.contextMenuManager.ContextMenuManager;
@ -19,6 +20,7 @@ import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.GenericSelectMenuInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.SpringApplication;
import java.util.Timer;
import java.util.concurrent.TimeUnit;
@ -26,9 +28,11 @@ import java.util.concurrent.TimeUnit;
public class JDAListener extends ListenerAdapter {
private final JDA jda;
private final String[] args;
public JDAListener(JDA jda) {
public JDAListener(JDA jda, String[] args) {
this.jda = jda;
this.args = args;
}
@Override
@ -46,6 +50,8 @@ public class JDAListener extends ListenerAdapter {
new Timer().scheduleAtFixedRate(new PollTimerTask(jda, Logger.altitudeLogs), TimeUnit.MINUTES.toMillis(1), TimeUnit.MINUTES.toMillis(5));
startSchedulers();
// RequestManager.init();
// Logger.altitudeLogs.info("Starting spring application");
// SpringApplication.run(AltitudeBot.class, args);
}
private void startSchedulers() {

View File

@ -13,7 +13,7 @@ public class Logger {
Logger.altitudeLogs = new AltitudeLogs().setTimeFormat("[HH:mm:ss] ");
try {
Logger.altitudeLogs
.setLogPath(new File(AltitudeBot.getInstance().getDataFolder()).getParent() + File.separator + "logs")
.setLogPath(new File(AltitudeBot.getInstance().getDataFolder()) + File.separator + "logs")
.setLogName("debug.log", LogLevel.DEBUG)
.setLogName("info.log", LogLevel.INFO)
.setLogName("warning.log", LogLevel.WARNING)

View File

@ -0,0 +1,2 @@
server:
port: 8001