diff --git a/.gitignore b/.gitignore
index a1c2a238a..af7e11dba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
# Compiled class file
*.class
-
+.idea/
+target/
+*.iml
# Log file
*.log
diff --git a/abstracto-application/command/command-base/pom.xml b/abstracto-application/command/command-base/pom.xml
new file mode 100644
index 000000000..e2426197d
--- /dev/null
+++ b/abstracto-application/command/command-base/pom.xml
@@ -0,0 +1,46 @@
+
+
+
+ dev.sheldan.abstracto.command
+ command
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+
+ command-base
+ pom
+
+ utility
+ support
+
+
+
+
+ dev.sheldan.abstracto.command
+ command-int
+ ${project.version}
+
+
+
+
+
+
+ maven-compiler-plugin
+
+
+
+ only
+
+ dev.sheldan.abstracto.command.annotations.CommandSpecProcessor
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/abstracto-application/command/command-base/support/pom.xml b/abstracto-application/command/command-base/support/pom.xml
new file mode 100644
index 000000000..77bd77348
--- /dev/null
+++ b/abstracto-application/command/command-base/support/pom.xml
@@ -0,0 +1,15 @@
+
+
+
+ command-base
+ dev.sheldan.abstracto.command
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ support
+
+
+
\ No newline at end of file
diff --git a/abstracto-application/command/command-base/support/src/main/java/dev/sheldan/abstracto/command/support/Help.java b/abstracto-application/command/command-base/support/src/main/java/dev/sheldan/abstracto/command/support/Help.java
new file mode 100644
index 000000000..d51d3a280
--- /dev/null
+++ b/abstracto-application/command/command-base/support/src/main/java/dev/sheldan/abstracto/command/support/Help.java
@@ -0,0 +1,38 @@
+package dev.sheldan.abstracto.command.support;
+
+import dev.sheldan.abstracto.command.Command;
+import dev.sheldan.abstracto.command.execution.Configuration;
+import dev.sheldan.abstracto.command.execution.Context;
+import dev.sheldan.abstracto.command.execution.Result;
+import dev.sheldan.abstracto.command.meta.CommandRegistry;
+import net.dv8tion.jda.api.EmbedBuilder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class Help implements Command {
+
+
+ @Autowired
+ private CommandRegistry registry;
+
+ @Override
+ public Result execute(Context context) {
+ EmbedBuilder builder = new EmbedBuilder();
+ registry.getAllCommands().forEach(command -> {
+ builder.addField(command.getConfiguration().getName(), command.getConfiguration().getDescription(), false);
+ });
+ context.getChannel().sendMessage(builder.build()).queue();
+ return Result.fromSuccess();
+ }
+
+ @Override
+ public Configuration getConfiguration() {
+ return Configuration.builder()
+ .name("help")
+ .module("utility")
+ .description("Prints the help")
+ .causesReaction(false)
+ .build();
+ }
+}
diff --git a/abstracto-application/command/command-base/utility/pom.xml b/abstracto-application/command/command-base/utility/pom.xml
new file mode 100644
index 000000000..c69b07136
--- /dev/null
+++ b/abstracto-application/command/command-base/utility/pom.xml
@@ -0,0 +1,15 @@
+
+
+
+ dev.sheldan.abstracto.command
+ command-base
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ utility
+
+
+
\ No newline at end of file
diff --git a/abstracto-application/command/command-base/utility/src/main/java/dev/sheldan/abstracto/command/utility/Echo.java b/abstracto-application/command/command-base/utility/src/main/java/dev/sheldan/abstracto/command/utility/Echo.java
new file mode 100644
index 000000000..ff4c4a61c
--- /dev/null
+++ b/abstracto-application/command/command-base/utility/src/main/java/dev/sheldan/abstracto/command/utility/Echo.java
@@ -0,0 +1,38 @@
+package dev.sheldan.abstracto.command.utility;
+
+import dev.sheldan.abstracto.command.Command;
+import dev.sheldan.abstracto.command.execution.Configuration;
+import dev.sheldan.abstracto.command.execution.Context;
+import dev.sheldan.abstracto.command.execution.Parameter;
+import dev.sheldan.abstracto.command.execution.Result;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class Echo implements Command {
+
+ @Override
+ public Result execute(Context context) {
+ StringBuilder sb = new StringBuilder();
+ context.getParameters().getParameters().forEach(o -> {
+ sb.append(o.toString());
+ });
+ context.getChannel().sendMessage(sb.toString()).queue();
+ return Result.fromSuccess();
+ }
+
+ @Override
+ public Configuration getConfiguration() {
+ List parameters = new ArrayList<>();
+ parameters.add(Parameter.builder().name("input").type(String.class).remainder(true).build());
+ return Configuration.builder()
+ .name("echo")
+ .module("utility")
+ .description("Echos the input back to the same channel")
+ .causesReaction(false)
+ .parameters(parameters)
+ .build();
+ }
+}
diff --git a/abstracto-application/command/command-base/utility/src/main/java/dev/sheldan/abstracto/command/utility/Ping.java b/abstracto-application/command/command-base/utility/src/main/java/dev/sheldan/abstracto/command/utility/Ping.java
new file mode 100644
index 000000000..746faa6c1
--- /dev/null
+++ b/abstracto-application/command/command-base/utility/src/main/java/dev/sheldan/abstracto/command/utility/Ping.java
@@ -0,0 +1,28 @@
+package dev.sheldan.abstracto.command.utility;
+
+import dev.sheldan.abstracto.command.Command;
+import dev.sheldan.abstracto.command.execution.Configuration;
+import dev.sheldan.abstracto.command.execution.Context;
+import dev.sheldan.abstracto.command.execution.Result;
+import org.springframework.stereotype.Service;
+
+@Service
+public class Ping implements Command {
+
+ @Override
+ public Result execute(Context context) {
+ long ping = context.getJda().getGatewayPing();
+ context.getChannel().sendMessage("Latency: " + ping + " ms.").queue();
+ return Result.fromSuccess();
+ }
+
+ @Override
+ public Configuration getConfiguration() {
+ return Configuration.builder()
+ .name("ping")
+ .module("utility")
+ .description("Prints the current bot latency to the discord api")
+ .causesReaction(false)
+ .build();
+ }
+}
diff --git a/abstracto-application/command/command-int/pom.xml b/abstracto-application/command/command-int/pom.xml
new file mode 100644
index 000000000..6a2d281ad
--- /dev/null
+++ b/abstracto-application/command/command-int/pom.xml
@@ -0,0 +1,36 @@
+
+
+
+ dev.sheldan.abstracto.command
+ command
+ 1.0-SNAPSHOT
+
+ 4.0.0
+ jar
+ 1.0-SNAPSHOT
+
+ command-int
+
+
+
+ net.dv8tion
+ JDA
+
+
+ club.minnced
+ opus-java
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/Command.java b/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/Command.java
new file mode 100644
index 000000000..859bb679c
--- /dev/null
+++ b/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/Command.java
@@ -0,0 +1,11 @@
+package dev.sheldan.abstracto.command;
+
+import dev.sheldan.abstracto.command.execution.Configuration;
+import dev.sheldan.abstracto.command.execution.Context;
+import dev.sheldan.abstracto.command.execution.Result;
+
+public interface Command {
+
+ Result execute(Context context);
+ Configuration getConfiguration();
+}
diff --git a/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Configuration.java b/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Configuration.java
new file mode 100644
index 000000000..4fbd64236
--- /dev/null
+++ b/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Configuration.java
@@ -0,0 +1,17 @@
+package dev.sheldan.abstracto.command.execution;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter @Setter @Builder
+public class Configuration {
+
+ private String name;
+ private String module;
+ private String description;
+ private List parameters;
+ private boolean causesReaction;
+}
diff --git a/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Context.java b/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Context.java
new file mode 100644
index 000000000..d91a0dc8a
--- /dev/null
+++ b/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Context.java
@@ -0,0 +1,18 @@
+package dev.sheldan.abstracto.command.execution;
+
+import lombok.Builder;
+import lombok.Getter;
+import net.dv8tion.jda.api.JDA;
+import net.dv8tion.jda.api.entities.Message;
+import net.dv8tion.jda.api.entities.TextChannel;
+import net.dv8tion.jda.api.entities.User;
+
+@Builder
+@Getter
+public class Context {
+ private TextChannel channel;
+ private User author;
+ private Message message;
+ private Parameters parameters;
+ private JDA jda;
+}
diff --git a/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Parameter.java b/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Parameter.java
new file mode 100644
index 000000000..07064af21
--- /dev/null
+++ b/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Parameter.java
@@ -0,0 +1,13 @@
+package dev.sheldan.abstracto.command.execution;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter @Setter @Builder
+public class Parameter {
+ private String name;
+ private Class type;
+ private boolean optional;
+ private boolean remainder;
+}
diff --git a/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Parameters.java b/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Parameters.java
new file mode 100644
index 000000000..705998e95
--- /dev/null
+++ b/abstracto-application/command/command-int/src/main/java/dev/sheldan/abstracto/command/execution/Parameters.java
@@ -0,0 +1,12 @@
+package dev.sheldan.abstracto.command.execution;
+
+import lombok.Builder;
+import lombok.Getter;
+
+import java.util.List;
+
+@Builder
+public class Parameters {
+ @Getter
+ private List