diff --git a/SheepstarModules/ModerationV1/.gitignore b/SheepstarModules/ModerationV1/.gitignore
new file mode 100644
index 0000000..fbdfb15
--- /dev/null
+++ b/SheepstarModules/ModerationV1/.gitignore
@@ -0,0 +1,3 @@
+# Project exclude paths
+/target/
+/.idea
\ No newline at end of file
diff --git a/SheepstarModules/ModerationV1/README.md b/SheepstarModules/ModerationV1/README.md
new file mode 100644
index 0000000..891f072
--- /dev/null
+++ b/SheepstarModules/ModerationV1/README.md
@@ -0,0 +1,2 @@
+# SheepstarModule-Moderation
+The official sheepstar moderation module
diff --git a/SheepstarModules/ModerationV1/pom.xml b/SheepstarModules/ModerationV1/pom.xml
new file mode 100644
index 0000000..1fd7c1c
--- /dev/null
+++ b/SheepstarModules/ModerationV1/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ xyz.sheepstar
+ SheepstarModule-Moderation
+ pre1.0.0
+
+
+ 8
+ 8
+
+
+
+
+ xyz.sheepstar
+ SheepstarCore
+ beta1.0.2
+
+
+
+
\ No newline at end of file
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/action/AutomaticUnbanAction.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/action/AutomaticUnbanAction.java
new file mode 100644
index 0000000..25f6a16
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/action/AutomaticUnbanAction.java
@@ -0,0 +1,38 @@
+package xyz.sheepstar.moderation.action;
+
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.User;
+import xyz.sheepstar.moderation.api.models.TempBanManager;
+import xyz.sheepstar.util.action.RepeatedAction;
+
+import java.time.LocalDateTime;
+
+public class AutomaticUnbanAction extends RepeatedAction {
+
+ private final TempBanManager tempBanManager = (TempBanManager) api.getDatabase().getTableFactory().getTable(TempBanManager.class);
+
+ @Override
+ public long time() {
+ return 3;
+ }
+
+ @Override
+ public void execute() {
+ tempBanManager.getEntries().forEach(entry -> {
+ LocalDateTime unbanDate = (LocalDateTime) entry.get("unban_date");
+
+ if (unbanDate.compareTo(LocalDateTime.now()) <= 0) {
+ Guild guild = api.getJDA().getGuildById((String) entry.get("guildID"));
+ User user = api.getJDA().retrieveUserById((String) entry.get("userID")).complete();
+
+ try {
+ guild.unban(user).complete();
+ } catch (Exception ignored) {
+ }
+
+ tempBanManager.unban(user, guild);
+ }
+ });
+ }
+
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/ModerationCommand.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/ModerationCommand.java
new file mode 100644
index 0000000..d969766
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/ModerationCommand.java
@@ -0,0 +1,26 @@
+package xyz.sheepstar.moderation.api;
+
+import net.dv8tion.jda.api.Permission;
+import xyz.sheepstar.util.bot.command.GuildCommand;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+
+public abstract class ModerationCommand extends GuildCommand {
+
+ /**
+ * Checks if a user is authorized (an administrator or a moderation)
+ *
+ * @param event The {@link GuildEventController} from the listener
+ * @return true
if the user is authorized, otherwise false
+ */
+ @Override
+ public boolean isAuthorized(GuildEventController event) {
+ if (event.getMember().hasPermission(Permission.ADMINISTRATOR)) return true;
+
+ String moderationRole = api.getBotManager().getSettingsManager().getSetting(event.getGuild(), "moderation", "moderation_role").toString();
+
+ if (moderationRole.isEmpty()) return false;
+
+ return event.getMember().getRoles().contains(jda.getRoleById(moderationRole));
+ }
+
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/entities/Infraction.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/entities/Infraction.java
new file mode 100644
index 0000000..cb4d26b
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/entities/Infraction.java
@@ -0,0 +1,79 @@
+package xyz.sheepstar.moderation.api.entities;
+
+import net.dv8tion.jda.api.entities.Member;
+
+import java.sql.Timestamp;
+
+public class Infraction {
+
+ private Member member;
+ private String reason;
+ private Timestamp timestamp;
+
+ /**
+ * Basic constructor of the {@link Infraction}
+ *
+ * @param member The member of the infraction
+ * @param reason The reason why the member has been warned
+ * @param timestamp The time when the user has been warned
+ */
+ public Infraction(Member member, String reason, Timestamp timestamp) {
+ this.member = member;
+ this.reason = reason;
+ this.timestamp = timestamp;
+ }
+
+ /**
+ * Gets the member of the infraction
+ *
+ * @return the member of the infraction
+ */
+ public Member getMember() {
+ return member;
+ }
+
+ /**
+ * Sets the member of the infraction
+ *
+ * @param member The new member of the infraction
+ */
+ public void setMember(Member member) {
+ this.member = member;
+ }
+
+ /**
+ * Gets the reason why the user has been warned
+ *
+ * @return the reason of the infraction
+ */
+ public String getReason() {
+ return reason;
+ }
+
+ /**
+ * Sets the reason of the infraction
+ *
+ * @param reason The reason of the infraction
+ */
+ public void setReason(String reason) {
+ this.reason = reason;
+ }
+
+ /**
+ * Gets the timestamp of the infraction
+ *
+ * @return the timestamp of the infraction
+ */
+ public Timestamp getTimestamp() {
+ return timestamp;
+ }
+
+ /**
+ * Sets the timestamp of the infraction
+ *
+ * @param timestamp The new timestamp of the infraction
+ */
+ public void setTimestamp(Timestamp timestamp) {
+ this.timestamp = timestamp;
+ }
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/models/InfractionsManager.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/models/InfractionsManager.java
new file mode 100644
index 0000000..9c20c6b
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/models/InfractionsManager.java
@@ -0,0 +1,67 @@
+package xyz.sheepstar.moderation.api.models;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import net.dv8tion.jda.api.entities.Member;
+import xyz.sheepstar.moderation.api.entities.Infraction;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+
+
+public class InfractionsManager extends SheepManager {
+
+ @Override
+ protected String tableName() {
+ return "moderation_infractions";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("guildID").add();
+ custom("clientID").add();
+ custom("reason").add();
+ custom("added").length(6).type(SQLType.TIMESTAMP).extras(new String[]{"DEFAULT CURRENT_TIMESTAMP(6)"}).add();
+ }
+
+ /**
+ * Warns a member in a guild
+ *
+ * @param member The member you want to warn
+ * @param reason The reason why you want to warn the member
+ */
+ public void warn(Member member, String reason) {
+ insert().value("guildID", member.getGuild().getId()).value("clientID", member.getId()).value("reason", reason).execute();
+ }
+
+ /**
+ * Warns a member in a guild without a reason
+ *
+ * @param member The member you want to warn
+ */
+ public void warn(Member member) {
+ warn(member, "No reason provided");
+ }
+
+ /**
+ * Clears all warnings of a member
+ *
+ * @param member The member from which you want to remove all warnings
+ */
+ public void clearWarnings(Member member) {
+ delete().where("guildID", member.getGuild().getId()).where("clientID", member.getId()).execute();
+ }
+
+ /**
+ * Gets all infractions of a member
+ * @param member The member you want to get the infractions from
+ * @return all infractions of the member
+ */
+ public ArrayList getInfractions(Member member) {
+ ArrayList infractions = new ArrayList<>();
+ select().where("guildID", member.getGuild().getId()).where("clientID", member.getId()).getResult().getList().forEach(entry ->
+ infractions.add(new Infraction(member, (String) entry.get("reason"), (Timestamp) entry.get("added"))));
+ return infractions;
+ }
+
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/models/TempBanManager.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/models/TempBanManager.java
new file mode 100644
index 0000000..d485da1
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/api/models/TempBanManager.java
@@ -0,0 +1,68 @@
+package xyz.sheepstar.moderation.api.models;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.User;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+
+public class TempBanManager extends SheepManager {
+
+ @Override
+ protected String tableName() {
+ return "moderation_temp_bans";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("userID").add();
+ custom("guildID").add();
+ custom("unban_date").type(SQLType.DATETIME).add();
+ }
+
+ /**
+ * Checks if a specific user is temp-banned on a specific guild
+ *
+ * @param user The user you want to check
+ * @param guild The guild you want to check
+ * @return true
if the specific user is temp-banned, otherwise false
+ */
+ public boolean isBanned(User user, Guild guild) {
+ return select().where("userID", user.getId()).where("guildID", guild.getId()).getResult().exists();
+ }
+
+ /**
+ * Temp-bans a specific user / adds the specific user to the table
+ * @param user The user you want to temp-ban
+ * @param guild The guild on which the user should be banned
+ * @param date The date when the user should be unbanned
+ */
+ public void ban(User user, Guild guild, Date date) {
+ if (isBanned(user, guild)) return;
+ insert().value("userID", user.getId()).value("guildID", guild.getId()).value("unban_date", date).execute();
+ }
+
+ /**
+ * Unbans a user / deletes a temp-ban from the table
+ *
+ * @param user The user you want to unban
+ * @param guild The guild on which the user should be unbanned
+ */
+ public void unban(User user, Guild guild) {
+ if (!isBanned(user, guild)) return;
+ delete().where("userID", user.getId()).where("guildID", guild.getId()).execute();
+ }
+
+ /**
+ * Gets all current banned users
+ *
+ * @return gets all entries from the table
+ */
+ public ArrayList> getEntries() {
+ return select().getResult().getList();
+ }
+
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/BanCommand.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/BanCommand.java
new file mode 100644
index 0000000..b99856d
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/BanCommand.java
@@ -0,0 +1,31 @@
+package xyz.sheepstar.moderation.commands;
+
+import net.dv8tion.jda.api.entities.User;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.moderation.api.ModerationCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+
+@CommandMeta(aliases = {"ban", "banuser"}, description = "Bans a member")
+public class BanCommand extends ModerationCommand {
+
+ @Override
+ public void usage() {
+ usage(OptionType.USER, "member", "The member you want to ban").required(true).add();
+ usage("reason", "The reason why the member should be banned").add();
+ usage(OptionType.INTEGER, "days", "Deletes messages from the past days").add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ User member = args.retrieveUser("member");
+ String reason = (args.exists("reason") ? args.getString("reason") : "No reason provided") + " (Banned by " + event.getAuthor().getAsTag() + ")";
+ int days = args.exists("days") ? args.getInteger("days") : 0;
+
+ event.getGuild().ban(member, days, reason).complete();
+
+ event.success("moderation.user_banned", member.getAsTag(), reason, days);
+ }
+
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/ClearCommand.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/ClearCommand.java
new file mode 100644
index 0000000..a5a2cbf
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/ClearCommand.java
@@ -0,0 +1,32 @@
+package xyz.sheepstar.moderation.commands;
+
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.moderation.api.ModerationCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+
+import java.time.OffsetDateTime;
+import java.time.temporal.ChronoUnit;
+
+@CommandMeta(aliases = "clear", description = "Clears a specific amount of messages in this chat")
+public class ClearCommand extends ModerationCommand {
+
+ @Override
+ public void usage() {
+ usage(OptionType.INTEGER, "amount", "The amount of messages to delete").required(true).add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ int amount = Math.min(args.getInteger("amount"), 100);
+
+ event.getChannel().getHistory().retrievePast(amount).queue(messages -> {
+ messages.removeIf(message -> message.getTimeCreated().isBefore(OffsetDateTime.now().minus(2, ChronoUnit.WEEKS)));
+
+ if (!messages.isEmpty()) event.getChannel().deleteMessages(messages).queue();
+
+ event.success("moderation.messages_cleared", amount, event.getChannel().getAsMention());
+ });
+ }
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/KickCommand.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/KickCommand.java
new file mode 100644
index 0000000..ea1aa14
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/KickCommand.java
@@ -0,0 +1,31 @@
+package xyz.sheepstar.moderation.commands;
+
+import net.dv8tion.jda.api.entities.Member;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.moderation.api.ModerationCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+
+@CommandMeta(aliases = {"kick", "kickuser"}, description = "Kicks a user from the server")
+public class KickCommand extends ModerationCommand {
+
+ @Override
+ public void usage() {
+ usage(OptionType.USER, "member", "The member you want to kick").required(true).add();
+ usage("reason", "The reason why you want to kick the member").add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+
+ Member member = event.getGuild().retrieveMemberById(args.getString("member")).complete();
+
+ String reason = args.exists("reason") ? args.getString("reason") : "No reason provided";
+
+ event.getGuild().kick(member, reason).complete();
+
+ event.success("moderation.user_kicked", member.getUser().getAsTag(), reason);
+ }
+
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/TempBanCommand.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/TempBanCommand.java
new file mode 100644
index 0000000..42a6908
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/TempBanCommand.java
@@ -0,0 +1,42 @@
+package xyz.sheepstar.moderation.commands;
+
+import net.dv8tion.jda.api.entities.User;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.moderation.api.ModerationCommand;
+import xyz.sheepstar.moderation.api.models.TempBanManager;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+
+import java.util.Date;
+
+@CommandMeta(aliases = {"tempban", "bantemp"}, description = "Bans a user for a specific amount of days")
+public class TempBanCommand extends ModerationCommand {
+
+ private final TempBanManager tempBanManager = (TempBanManager) table(TempBanManager.class);
+
+ @Override
+ public void usage() {
+ usage(OptionType.USER, "member", "The member you want to ban").required(true).add();
+ usage("time", "The amount of time the user should be banned (ex. 3d2h5m)").required(true).add();
+ usage("reason", "The reason why the member should be banned").add();
+ usage(OptionType.INTEGER, "days", "Deletes messages from the past days").add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ User member = args.retrieveUser("member");
+ int days = args.exists("days") ? args.getInteger("days") : 0;
+
+ Date date = getTimeFromString(args.getString("time"));
+
+ String reason = (args.exists("reason") ? args.getString("reason") : "No reason provided")
+ + " (Temp-banned by " + event.getAuthor().getAsTag() + ", automatically unbans at " + date + ")";
+
+ tempBanManager.ban(member, event.getGuild(), date);
+
+ event.getGuild().ban(member, days, reason).complete();
+
+ event.success("moderation.user_temp_banned", member.getAsTag(), reason, days, date);
+ }
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/UnbanCommand.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/UnbanCommand.java
new file mode 100644
index 0000000..1b0d90f
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/UnbanCommand.java
@@ -0,0 +1,26 @@
+package xyz.sheepstar.moderation.commands;
+
+import net.dv8tion.jda.api.entities.User;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.moderation.api.ModerationCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+
+@CommandMeta(aliases = "unban", description = "Unbans a user")
+public class UnbanCommand extends ModerationCommand {
+
+ @Override
+ public void usage() {
+ usage(OptionType.USER, "member", "The member you want to unban").required(true).add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ User member = args.retrieveUser("member");
+
+ event.getGuild().unban(member).complete();
+
+ event.success("moderation.user_unbanned", member.getAsTag());
+ }
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/UserInfoCommand.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/UserInfoCommand.java
new file mode 100644
index 0000000..f4f9488
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/UserInfoCommand.java
@@ -0,0 +1,69 @@
+package xyz.sheepstar.moderation.commands;
+
+import net.dv8tion.jda.api.entities.Member;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.moderation.api.ModerationCommand;
+import xyz.sheepstar.util.bot.builder.message.DefaultEmbedBuilder;
+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.emote.INTERN_EMOTE;
+
+import java.time.OffsetDateTime;
+
+@CommandMeta(aliases = "userinfo", description = "Shows the information of an user")
+public class UserInfoCommand extends ModerationCommand {
+
+ @Override
+ public void usage() {
+ usage(OptionType.USER, "member", "The member you want the info from").required(true).add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ Member target = event.getGuild().retrieveMemberById(args.getString("member")).complete();
+
+ String boostedTime = target.getTimeBoosted() == null ? ":x: Not boosting" : toUnix(target.getTimeBoosted());
+
+ DefaultEmbedBuilder builder = new DefaultEmbedBuilder(MessageType.PRIMARY)
+ .setTitle(":information_source: " + translate("moderation.userinfo", event.getGuild()))
+ .addField(":id: " + translate("moderation.client_id", event.getGuild()), target.getId(), true)
+ .addField(":pencil: " + translate("moderation.username", event.getGuild()), target.getUser().getAsTag(), true)
+ .addField(getEmoteString(INTERN_EMOTE.NITRO) + " " + translate("moderation.boosting_since", event.getGuild()), boostedTime, true)
+ .addField(String.format(":open_file_folder: %s (%s)", translate("moderation.roles", event.getGuild()), target.getRoles().size()),
+ getRoleText(target), true)
+ .addField(":date: " + translate("moderation.joined_date", event.getGuild()), toUnix(target.getTimeJoined()), true)
+ .addField(":date: " + translate("moderation.creation_date", event.getGuild()), toUnix(target.getTimeCreated()), true)
+ .setColor(target.getColor())
+ .setThumbnail(target.getUser().getAvatarUrl());
+
+ event.reply(builder.toMessage());
+ }
+
+ /**
+ * Converts the provided timestamp to a valid discord unix timestamp
+ *
+ * @param time The timestamp you want to view
+ * @return the created discord unix timestamp
+ */
+ public String toUnix(OffsetDateTime time) {
+ return String.format("", (time.toInstant().toEpochMilli() / 1000));
+ }
+
+ /**
+ * Gets the text of the role
+ *
+ * @param target The member you want to get
+ * @return the roles as a string
+ */
+ public String getRoleText(Member target) {
+ StringBuilder roleText = new StringBuilder();
+ target.getRoles().forEach(role -> {
+ if (!roleText.toString().isEmpty()) roleText.append(", ");
+ roleText.append(role.getAsMention());
+ });
+ return roleText.toString();
+ }
+
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/infractions/WarnCommand.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/infractions/WarnCommand.java
new file mode 100644
index 0000000..4b1ccca
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/infractions/WarnCommand.java
@@ -0,0 +1,33 @@
+package xyz.sheepstar.moderation.commands.infractions;
+
+import net.dv8tion.jda.api.entities.Member;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.moderation.api.ModerationCommand;
+import xyz.sheepstar.moderation.api.models.InfractionsManager;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+
+@CommandMeta(aliases = {"warn", "warnuser"}, description = "Warns a user")
+public class WarnCommand extends ModerationCommand {
+
+ private InfractionsManager infractionsManager = (InfractionsManager) table(InfractionsManager.class);
+
+ @Override
+ public void usage() {
+ usage(OptionType.USER, "member", "The member you want to warn").required(true).add();
+ usage("reason", "The reason why you want to warn the user").add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ Member member = event.getGuild().retrieveMemberById(args.getString("member")).complete();
+
+ String reason = args.exists("reason") ? args.getString("reason") : "No reason provided";
+
+ infractionsManager.warn(member, reason);
+
+ event.success("moderation.user_warned", member.getUser().getAsTag(), reason);
+ }
+
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/infractions/WarningsCommand.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/infractions/WarningsCommand.java
new file mode 100644
index 0000000..b590524
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/commands/infractions/WarningsCommand.java
@@ -0,0 +1,57 @@
+package xyz.sheepstar.moderation.commands.infractions;
+
+import net.dv8tion.jda.api.entities.Emoji;
+import net.dv8tion.jda.api.entities.Member;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.components.ButtonStyle;
+import xyz.sheepstar.moderation.api.ModerationCommand;
+import xyz.sheepstar.moderation.api.models.InfractionsManager;
+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;
+
+@CommandMeta(aliases = {"warnings", "listwarns", "listwarnings"}, description = "Shows you all infractions/warnings of a user")
+public class WarningsCommand extends ModerationCommand {
+
+ private InfractionsManager infractionsManager = (InfractionsManager) table(InfractionsManager.class);
+
+ @Override
+ public void usage() {
+ usage(OptionType.USER, "member", "The member you want to get the infractions from").required(true).add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ Member member = event.getGuild().retrieveMemberById(args.getString("member")).complete();
+
+ StringBuilder infractions = new StringBuilder();
+
+ infractionsManager.getInfractions(member).forEach(infraction -> {
+ if (!infractions.toString().isEmpty()) infractions.append("\n");
+ infractions.append("`").append(infraction.getReason()).append("`").append(" *").
+ append(String.format("", infraction.getTimestamp().getTime() / 1000)).append("*");
+ });
+
+ if (infractions.toString().isEmpty())
+ infractions.append(":no_entry_sign: The member currently has no warnings");
+
+ event.custom(MessageType.PRIMARY)
+ .withTitle(translate("moderation.infractions", event.getLanguage(), member.getUser().getName()))
+ .withDescription(infractions.toString())
+ .addButton(ButtonStyle.DANGER, "clear#" + args.getString("member"), "Clear all", Emoji.fromUnicode("\uD83D\uDDD1️"))
+ .send();
+ }
+
+ @Override
+ public void buttonClick(GuildEventController event, String id) throws Exception {
+ if (!id.startsWith("clear#")) return;
+
+ Member member = event.getGuild().retrieveMemberById(id.split("#")[1]).complete();
+
+ infractionsManager.clearWarnings(member);
+
+ event.success("moderation.cleared_warnings", member.getUser().getAsTag());
+ }
+
+}
diff --git a/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/core/ModerationCore.java b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/core/ModerationCore.java
new file mode 100644
index 0000000..54bde79
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/java/xyz/sheepstar/moderation/core/ModerationCore.java
@@ -0,0 +1,54 @@
+package xyz.sheepstar.moderation.core;
+
+import xyz.sheepstar.moderation.action.AutomaticUnbanAction;
+import xyz.sheepstar.moderation.api.models.InfractionsManager;
+import xyz.sheepstar.moderation.commands.*;
+import xyz.sheepstar.moderation.api.models.TempBanManager;
+import xyz.sheepstar.moderation.commands.infractions.WarningsCommand;
+import xyz.sheepstar.moderation.commands.infractions.WarnCommand;
+import xyz.sheepstar.util.bot.manager.ImportManager;
+import xyz.sheepstar.util.module.SheepstarModule;
+
+public class ModerationCore extends SheepstarModule {
+
+ private ImportManager importManager;
+
+ @Override
+ public void onEnable() {
+ importManager = new ImportManager(getAPI(), "moderation");
+
+ registerManagers();
+ registerCommands();
+ registerActions();
+ }
+
+ /**
+ * Registers all commands of the moderation module
+ */
+ public void registerCommands() {
+ importManager.registerCommand(new BanCommand());
+ importManager.registerCommand(new UnbanCommand());
+ importManager.registerCommand(new TempBanCommand());
+ importManager.registerCommand(new KickCommand());
+ importManager.registerCommand(new UserInfoCommand());
+ importManager.registerCommand(new WarnCommand());
+ importManager.registerCommand(new WarningsCommand());
+ importManager.registerCommands(new ClearCommand());
+ }
+
+ /**
+ * Registers all managers of this module
+ */
+ public void registerManagers() {
+ registerTable(new TempBanManager());
+ registerTable(new InfractionsManager());
+ }
+
+ /**
+ * Registers all actions of this module
+ */
+ public void registerActions() {
+ new AutomaticUnbanAction().start();
+ }
+
+}
diff --git a/SheepstarModules/ModerationV1/src/main/resources/module.yml b/SheepstarModules/ModerationV1/src/main/resources/module.yml
new file mode 100644
index 0000000..efbbecb
--- /dev/null
+++ b/SheepstarModules/ModerationV1/src/main/resources/module.yml
@@ -0,0 +1,3 @@
+main: xyz.sheepstar.moderation.core.ModerationCore
+name: moderation
+author: Mathias Wagner
\ No newline at end of file