diff --git a/SheepstarModules/GlobalV1/.gitignore b/SheepstarModules/GlobalV1/.gitignore
new file mode 100644
index 0000000..fbdfb15
--- /dev/null
+++ b/SheepstarModules/GlobalV1/.gitignore
@@ -0,0 +1,3 @@
+# Project exclude paths
+/target/
+/.idea
\ No newline at end of file
diff --git a/SheepstarModules/GlobalV1/README.md b/SheepstarModules/GlobalV1/README.md
new file mode 100644
index 0000000..4c343ed
--- /dev/null
+++ b/SheepstarModules/GlobalV1/README.md
@@ -0,0 +1,2 @@
+# SheepstarModule-Global
+The official sheepstar global module
diff --git a/SheepstarModules/GlobalV1/pom.xml b/SheepstarModules/GlobalV1/pom.xml
new file mode 100644
index 0000000..334a24c
--- /dev/null
+++ b/SheepstarModules/GlobalV1/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ xyz.sheepstar
+ SheepstarModule-Global
+ 1.0.0
+
+
+ 8
+ 8
+
+
+
+
+ xyz.sheepstar
+ SheepstarCore
+ beta1.0.2
+
+
+
+
\ No newline at end of file
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/DesignManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/DesignManager.java
new file mode 100644
index 0000000..d58f7c1
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/DesignManager.java
@@ -0,0 +1,135 @@
+package xyz.sheepstar.global.api;
+
+import net.dv8tion.jda.api.MessageBuilder;
+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 xyz.sheepstar.util.bot.builder.message.DefaultEmbedBuilder;
+import xyz.sheepstar.util.bot.listener.ListenerBasics;
+import xyz.sheepstar.util.bot.manager.sql.SettingsManager;
+
+import java.awt.*;
+import java.util.Date;
+
+public class DesignManager extends ListenerBasics {
+
+ private final SettingsManager settingsManager = api.getBotManager().getSettingsManager();
+
+ /**
+ * Gets a design by id
+ *
+ * @param design The design you want to get
+ * @param guild The guild the message should display
+ * @param author The author the message should display
+ * @param message The message that should display
+ * @return the created message by design
+ */
+ public Message getDesign(String design, Guild guild, Member author, String message) {
+ switch (design) {
+ case "2":
+ return getDesign2(guild, author, message);
+ case "3":
+ return getDesign3(author.getUser(), message);
+ case "4":
+ return getDesign4(author.getUser(), message);
+ case "5":
+ return getDesign5(author.getUser(), message);
+ default:
+ return getDesign1(guild, author, message);
+ }
+ }
+
+ /**
+ * Gets the first design
+ *
+ * @param guild The guild that should be displayed
+ * @param author The author that should be displayed
+ * @param message The message that should be displayed
+ * @return the message created by the design
+ */
+ private Message getDesign1(Guild guild, Member author, String message) {
+ DefaultEmbedBuilder eb = new DefaultEmbedBuilder();
+
+ // Set the icon
+ eb.setThumbnail(guild.getIconUrl() != null ? guild.getIconUrl() : "http://cdn.sheepstar.xyz/0f409da574c9136b.gif");
+
+ eb.setTimestamp(new Date().toInstant());
+
+ eb.setFooter(translate("global.message.sent_by", guild, guild.getName()));
+
+ // Links
+ String links = "[Support Server](https://discord.gg/jbne9JTJtU) ║ [Bot Invite](https://discord.com/api/oauth2/authorize?client_id=772513556116930580&permissions=321536&scope=bot)";
+ eb.addField("", links, false);
+
+ eb.setDescription(message);
+ eb.setAuthor(author.getUser().getAsTag(), null, author.getUser().getAvatarUrl());
+
+ String colorString = settingsManager.getSettingString(guild, "global", "message_color");
+ if (colorString.equals("role"))
+ eb.setColor(author.getColor());
+ else eb.setColor(Color.decode(colorString));
+
+ return new MessageBuilder().setEmbed(eb.build()).build();
+ }
+
+ /**
+ * Gets the second design
+ *
+ * @param guild The guild that should be displayed
+ * @param author The author that should be displayed
+ * @param message The message that should be displayed
+ * @return the message created by the design
+ */
+ private Message getDesign2(Guild guild, Member author, String message) {
+ DefaultEmbedBuilder eb = new DefaultEmbedBuilder();
+
+ eb.setTimestamp(new Date().toInstant());
+
+ eb.setFooter(translate("global.message.sent_by", guild, guild.getName()), guild.getIconUrl() != null ? guild.getIconUrl() : "http://cdn.sheepstar.xyz/0f409da574c9136b.gif");
+
+ eb.setDescription(message);
+ eb.setAuthor(author.getUser().getAsTag(), null, author.getUser().getAvatarUrl());
+
+ String colorString = settingsManager.getSettingString(guild, "global", "message_color");
+ if (colorString.equals("role"))
+ eb.setColor(author.getColor());
+ else eb.setColor(Color.decode(colorString));
+
+ return new MessageBuilder().setEmbed(eb.build()).build();
+ }
+
+ /**
+ * Gets the third design
+ *
+ * @param author The author that should be displayed
+ * @param message The message that should be displayed
+ * @return the message created by the design
+ */
+ private Message getDesign3(User author, String message) {
+ return new MessageBuilder().setContent(String.format("[%s] %s", author.getAsTag(), message)).build();
+ }
+
+ /**
+ * Gets the 4th design
+ *
+ * @param author The author that should be displayed
+ * @param message The message that should be displayed
+ * @return the message created by the design
+ */
+ private Message getDesign4(User author, String message) {
+ return new MessageBuilder().setContent(String.format("%s » %s", author.getAsTag(), message)).build();
+ }
+
+ /**
+ * Gets the 5th design
+ *
+ * @param author The author that should be displayed
+ * @param message The message that should be displayed
+ * @return the message created by the design
+ */
+ private Message getDesign5(User author, String message) {
+ return new MessageBuilder().setContent(String.format("**%s**: %s", author.getAsTag(), message)).build();
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalCommand.java
new file mode 100644
index 0000000..b518494
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalCommand.java
@@ -0,0 +1,114 @@
+package xyz.sheepstar.global.api;
+
+import xyz.sheepstar.global.api.models.GlobalManager;
+import xyz.sheepstar.global.api.models.GlobalUserSlowMode;
+import xyz.sheepstar.global.api.models.RoomCategoryManager;
+import xyz.sheepstar.global.api.models.RoomManager;
+import xyz.sheepstar.global.api.models.ban.*;
+import xyz.sheepstar.global.api.models.emote.GlobalEmoteManager;
+import xyz.sheepstar.global.api.models.log.LogManager;
+import xyz.sheepstar.global.core.GlobalBootstrap;
+import xyz.sheepstar.util.bot.command.GuildCommand;
+
+public abstract class GlobalCommand extends GuildCommand {
+
+ /**
+ * Gets the global manager
+ *
+ * @return the global manager
+ */
+ public GlobalManager getGlobalManager() {
+ return (GlobalManager) table(GlobalManager.class);
+ }
+
+ /**
+ * Gets the slow-mode table
+ *
+ * @return the slow-mode table
+ */
+ public GlobalUserSlowMode getSlowMode() {
+ return (GlobalUserSlowMode) table(GlobalUserSlowMode.class);
+ }
+
+ /**
+ * Gets the category manager
+ *
+ * @return the category manager
+ */
+ public RoomCategoryManager getCategoryManager() {
+ return (RoomCategoryManager) table(RoomCategoryManager.class);
+ }
+
+ /**
+ * Gets the room manager
+ *
+ * @return the room manager
+ */
+ public RoomManager getRoomManager() {
+ return (RoomManager) table(RoomManager.class);
+ }
+
+ /**
+ * Gets the emote manager
+ *
+ * @return the emote manager
+ */
+ public GlobalEmoteManager getEmoteManager() {
+ return GlobalBootstrap.getEmoteManager();
+ }
+
+ /**
+ * Gets the user ban manager
+ *
+ * @return the user ban manager
+ */
+ public UserBanManager getUserBanManager() {
+ return (UserBanManager) table(UserBanManager.class);
+ }
+
+ /**
+ * Gets the server ban manager
+ *
+ * @return the server ban manager
+ */
+ public ServerBanManager getServerBanManager() {
+ return (ServerBanManager) table(ServerBanManager.class);
+ }
+
+ /**
+ * Gets the user ban log manager
+ *
+ * @return the user ban log manager
+ */
+ public UserBanLogManager getUserBanLogManager() {
+ return (UserBanLogManager) table(UserBanLogManager.class);
+ }
+
+ /**
+ * Gets the server ban log manager
+ *
+ * @return the server ban log manager
+ */
+ public ServerBanLogManager getServerBanLogManager() {
+ return (ServerBanLogManager) table(ServerBanLogManager.class);
+ }
+
+ /**
+ * Gets the report manager
+ *
+ * @return the report manager
+ */
+ public ReportManager getReportManager() {
+ return (ReportManager) table(ReportManager.class);
+ }
+
+ /**
+ * Gets the log manager
+ *
+ * @return the log manager
+ */
+ public LogManager getLogManager() {
+ return (LogManager) table(LogManager.class);
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalValidation.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalValidation.java
new file mode 100644
index 0000000..a7b294d
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalValidation.java
@@ -0,0 +1,76 @@
+package xyz.sheepstar.global.api;
+
+import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
+import xyz.sheepstar.global.api.models.GlobalUserSlowMode;
+import xyz.sheepstar.global.api.models.ban.ServerBanManager;
+import xyz.sheepstar.global.api.models.ban.UserBanManager;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.listener.GuildListener;
+
+public class GlobalValidation extends GuildListener {
+
+ GlobalUserSlowMode slowMode = (GlobalUserSlowMode) table(GlobalUserSlowMode.class);
+ UserBanManager userBan = (UserBanManager) table(UserBanManager.class);
+ ServerBanManager serverBan = (ServerBanManager) table(ServerBanManager.class);
+
+ /**
+ * Validates the global message received event
+ *
+ * @param event The {@link GuildEventController} from the listener
+ * @return true
if all validation checks have been passed, otherwise false
+ */
+ public boolean validate(GuildEventController event) throws PublicCommandException {
+ GuildMessageReceivedEvent receivedEvent = (GuildMessageReceivedEvent) event.getEvent();
+ String messageContent = receivedEvent.getMessage().getContentRaw();
+ String lowerContent = messageContent.toLowerCase();
+
+ // Check if the bot is tagged
+ if (messageContent.startsWith(String.format("<@!%s>", jda.getSelfUser().getId()))) return false;
+
+ // Check if message starts with '='
+ if (messageContent.startsWith("=")) return false;
+
+ runIgnored(() -> receivedEvent.getMessage().delete().queue(s -> {}, t -> {}));
+
+ if (messageContent.equals("del")) return false;
+
+ // Check if message starts with the prefix of the module
+ if (messageContent.startsWith(moduleManager.getPrefix(event.getGuild(), "global"))) return false;
+
+ if (messageContent.length() >= 1000) throw new PublicCommandException("global.message.too_big");
+
+ // Check if user is banned
+ if (userBan.isBanned(event.getAuthor())) throw new PublicCommandException("global.user_banned");
+
+ // Check if server is banned
+ if (serverBan.isBanned(event.getGuild())) throw new PublicCommandException("global.guild_banned");
+
+ // Check if message contains an url
+ if (!api.isOwner(event.getAuthor()) && containsAll(lowerContent, "https://", "http://", "www."))
+ throw new PublicCommandException("global.ads.not_allowed");
+
+ // Check if the user can write
+ if (!slowMode.canWrite(event.getAuthor())) {
+ throw new PublicCommandException("global.spam.please_wait", slowMode.getNeededTime(event.getAuthor()));
+ } else slowMode.updateUser(event.getAuthor());
+
+ if (messageContent.isEmpty()) throw new PublicCommandException("global.message.not_supported");
+
+ return true;
+ }
+
+ /**
+ * Checks if a string contains the provided words
+ *
+ * @param baseString The string you want to check
+ * @param containList The list of words that should be tested
+ * @return true
if the string contains the provided words, otherwise false
+ */
+ public boolean containsAll(String baseString, String... containList) {
+ for (String current : containList)
+ if (baseString.contains(current)) return true;
+ return false;
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalValidator.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalValidator.java
new file mode 100644
index 0000000..1161e6e
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalValidator.java
@@ -0,0 +1,18 @@
+package xyz.sheepstar.global.api;
+
+import xyz.sheepstar.global.api.models.GlobalManager;
+import xyz.sheepstar.global.core.GlobalBootstrap;
+import xyz.sheepstar.util.SheepstarImpl;
+import xyz.sheepstar.util.validation.trigger.TriggerValidation;
+
+public class GlobalValidator extends TriggerValidation {
+
+ private final SheepstarImpl api = (SheepstarImpl) GlobalBootstrap.getApi();
+ private final GlobalManager global = (GlobalManager) api.getDatabase().getTableFactory().getTable(GlobalManager.class);
+
+ @Override
+ public boolean validate(Object o) {
+ return global.isRegistered(api.getJDA().getTextChannelById(o.toString()));
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/GlobalManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/GlobalManager.java
new file mode 100644
index 0000000..9e2a830
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/GlobalManager.java
@@ -0,0 +1,169 @@
+package xyz.sheepstar.global.api.models;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.TextChannel;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.util.ArrayList;
+
+public class GlobalManager extends SheepManager {
+
+ private final RoomManager roomManager = (RoomManager) table(RoomManager.class);
+
+ @Override
+ protected String tableName() {
+ return "global_channels";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("guildID").type(SQLType.VARCHAR).length(20).add();
+ custom("channelID").type(SQLType.VARCHAR).length(20).add();
+
+ custom("language").type(SQLType.VARCHAR).length(5).defaultValue("en").add();
+ custom("designID").type(SQLType.VARCHAR).length(5).defaultValue("1").add();
+
+ custom("roomID").type(SQLType.VARCHAR).length(10).defaultValue("1").add();
+ }
+
+ /**
+ * Checks if the provided text-channel is a global channel
+ *
+ * @param textChannel The text-channel you want to check
+ * @return true
if the text-channel is a global channel (registered), otherwise false
+ */
+ public boolean isRegistered(TextChannel textChannel) {
+ return containsRow("channelID", textChannel.getId());
+ }
+
+ /**
+ * Registers a text-channel
+ *
+ * @param channel The channel you want to register
+ */
+ public void register(TextChannel channel) {
+ register(channel, "en");
+ }
+
+ /**
+ * Registers a text-channel with a language code
+ *
+ * @param channel The channel you want to register
+ * @param languageCode The language code you want to use
+ */
+ public void register(TextChannel channel, String languageCode) {
+ if (isRegistered(channel)) return;
+ insert().value("guildID", channel.getGuild().getId()).value("channelID", channel.getId()).value("language", languageCode).execute();
+ }
+
+ /**
+ * Unregisters a channel (transforms it back to a normal channel)
+ *
+ * @param channel The channel you want to unregister
+ */
+ public void unregister(TextChannel channel) {
+ if (!isRegistered(channel)) return;
+ delete("channelID", channel.getId());
+ }
+
+ /**
+ * Unregisters a channel by id
+ *
+ * @param channelId The id of the channel you want to unregister
+ */
+ public void unregister(String channelId) {
+ delete("channelID", channelId);
+ }
+
+ /**
+ * Gets the room of a registered global channel
+ *
+ * @param channel The channel you want to get the room from
+ * @return the room of the global channel
+ */
+ public String getRoom(TextChannel channel) {
+ return getString("channelID", channel.getId(), "roomID");
+ }
+
+ /**
+ * Gets the language of a registered global channel
+ *
+ * @param channel The channel you want to get the language from
+ * @return the language of the global channel
+ */
+ public String getLanguage(TextChannel channel) {
+ return getString("channelID", channel.getId(), "language");
+ }
+
+ /**
+ * Clears the list of channels from a guild
+ *
+ * @param guild The guild you want to remove the channels from
+ */
+ public void clearList(Guild guild) {
+ delete("guildID", guild.getId());
+ }
+
+ /**
+ * Sets the language of a global channel
+ *
+ * @param channel The channel you want to use
+ * @param toLanguage The new language of the channel
+ */
+ public void setLanguage(TextChannel channel, String toLanguage) {
+ if (!api.getBotManager().getLanguageManager().exists(toLanguage)) return;
+ updateString("channelID", channel.getId(), "language", toLanguage);
+ }
+
+ /**
+ * Sets the room of a global channel
+ *
+ * @param channel The channel you want to use
+ * @param toRoom The new room of the channel
+ */
+ public void setRoom(TextChannel channel, String toRoom) {
+ if (!roomManager.exists(toRoom)) return;
+ updateString("channelID", channel.getId(), "roomID", toRoom);
+ }
+
+ /**
+ * Gets the count of registered global channels by a guild
+ *
+ * @param guild The guild you want to get the channel count from
+ * @return the amount of registered global channels
+ */
+ public int getChannelCount(Guild guild) {
+ return getRowCount("guildID", guild.getId());
+ }
+
+ /**
+ * Gets the current design of a global channel
+ *
+ * @param channel The channel you want to get the design from
+ * @return the design of the global channel
+ */
+ public String getDesign(TextChannel channel) {
+ return getString("channelID", channel.getId(), "designID");
+ }
+
+ /**
+ * Sets the design of a global channel
+ *
+ * @param channel The channel you want to use
+ * @param toDesign The new design you want to set to the channel
+ */
+ public void setDesign(TextChannel channel, String toDesign) {
+ updateString("channelID", channel.getId(), "designID", toDesign);
+ }
+
+
+ /**
+ * Gets all registered global channels
+ *
+ * @return all registered global channels
+ */
+ public ArrayList getChannels() {
+ return select().getResult().getList("channelID");
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/GlobalUserSlowMode.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/GlobalUserSlowMode.java
new file mode 100644
index 0000000..26e8a02
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/GlobalUserSlowMode.java
@@ -0,0 +1,100 @@
+package xyz.sheepstar.global.api.models;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import net.dv8tion.jda.api.entities.User;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+public class GlobalUserSlowMode extends SheepManager {
+
+ @Override
+ protected String tableName() {
+ return "global_user_slowmode";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("clientID").length(50).add();
+ custom("lastMessage").length(6).type(SQLType.TIMESTAMP).allowNull(true).extras(new String[]{"DEFAULT CURRENT_TIMESTAMP(6)"}).add();
+ }
+
+ /**
+ * Checks if the provided user is registered
+ *
+ * @param user The user you want to check
+ * @return true
if the provided user is registered, otherwise false
+ */
+ public boolean isRegistered(User user) {
+ return select().where("clientID", user.getId()).getResult().getRowCount() == 1;
+ }
+
+ /**
+ * Registers a user
+ *
+ * @param user The user you want to register
+ */
+ public void registerUser(User user) {
+ if (isRegistered(user)) return;
+ insert().value("clientID", user.getId()).execute();
+ }
+
+ /**
+ * Updates the slow-time of the user
+ *
+ * @param user The user you want to update
+ */
+ public void updateUser(User user) {
+ if (!isRegistered(user)) registerUser(user);
+ update().where("clientID", user.getId()).set("lastMessage", new Date()).execute();
+ }
+
+ /**
+ * Deletes a user from the slow-mode
+ *
+ * @param user The user you want to delete
+ */
+ public void delete(User user) {
+ if (!isRegistered(user)) return;
+ delete().where("clientID", user.getId()).execute();
+ }
+
+ /**
+ * Gets the time of the user
+ *
+ * @param user The user you want to get the time from
+ * @return the current timestamp
+ */
+ public Timestamp getTime(User user) {
+ if (!isRegistered(user)) registerUser(user);
+ return select().where("clientID", user.getId()).getResult().getTimestamp("lastMessage");
+ }
+
+ /**
+ * Checks if the provided user is allowed to write new messages
+ *
+ * @param user The user you want to check
+ * @return true
if the provided user can write, otherwise false
+ */
+ public boolean canWrite(User user) {
+ if (!isRegistered(user)) {
+ registerUser(user);
+ return true;
+ }
+ return getTime(user).toLocalDateTime().plusSeconds(3).compareTo(LocalDateTime.now()) <= 0;
+ }
+
+ /**
+ * Gets the needed time for the user to write a new message
+ *
+ * @param user The user you want to get the needed time from
+ * @return the needed time in seconds
+ */
+ public int getNeededTime(User user) {
+ int time = (getTime(user).toLocalDateTime().getSecond() - LocalDateTime.now().getSecond()) + 3;
+ return time != 61 ? time : 1;
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/RoomCategoryManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/RoomCategoryManager.java
new file mode 100644
index 0000000..3a87b77
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/RoomCategoryManager.java
@@ -0,0 +1,116 @@
+package xyz.sheepstar.global.api.models;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class RoomCategoryManager extends SheepManager {
+
+ @Override
+ protected String tableName() {
+ return "global_room_categories";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("code").type(SQLType.VARCHAR).length(10).add();
+ custom("name").type(SQLType.VARCHAR).length(25).add();
+ custom("description").type(SQLType.VARCHAR).length(50).add();
+ custom("reaction").type(SQLType.VARCHAR).length(25).add();
+ }
+
+ /**
+ * Checks if a room category exists
+ *
+ * @param code The code of the category
+ * @return true
if the category exists, otherwise false
+ */
+ public boolean exists(String code) {
+ return containsRow("code", code);
+ }
+
+ /**
+ * Creates a new category
+ *
+ * @param code The code of the category
+ * @param name The name of the category
+ * @param description The description of the category
+ * @param reaction The reaction of the category
+ */
+ public void create(String code, String name, String description, String reaction) {
+ if (exists(code)) return;
+ insert().value("code", code).value("name", name).value("description", description).value("reaction", reaction).execute();
+ }
+
+ /**
+ * Deletes a category
+ *
+ * @param code The code of the category you want to delete
+ */
+ public void delete(String code) {
+ if (!exists(code)) return;
+ delete("code", code);
+ }
+
+ /**
+ * Changes the name of a category
+ *
+ * @param code The code of the category
+ * @param toName The new name the category should have
+ */
+ public void changeName(String code, String toName) {
+ updateString("code", code, "name", toName);
+ }
+
+ /**
+ * Changes the description of a category
+ *
+ * @param code The code of the category
+ * @param toDescription The new description the category should have
+ */
+ public void changeDescription(String code, String toDescription) {
+ updateString("code", code, "description", toDescription);
+ }
+
+ /**
+ * Changes the reaction of the category
+ *
+ * @param code The code of the category
+ * @param toReaction The new reaction the category should have
+ */
+ public void changeReaction(String code, String toReaction) {
+ updateString("code", code, "reaction", toReaction);
+ }
+
+ /**
+ * Gets all current categories as a list
+ *
+ * @return all current categories as a list
+ */
+ public ArrayList> getCategories() {
+ return select().getResult().getList();
+ }
+
+ /**
+ * Gets the name of a category from a reaction
+ *
+ * @param reactionID The reaction id you want to use to get the name
+ * @return the name of the category
+ */
+ public String getNameFromReaction(String reactionID) {
+ return select().where("reaction", reactionID).getResult().getString("name");
+ }
+
+ /**
+ * Gets the code of a category from a reaction
+ *
+ * @param reactionID The reaction id you want to use to get the code
+ * @return the code of the category
+ */
+ public String getCodeFromReaction(String reactionID) {
+ return select().where("reaction", reactionID).getResult().getString("code");
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/RoomManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/RoomManager.java
new file mode 100644
index 0000000..888878e
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/RoomManager.java
@@ -0,0 +1,133 @@
+package xyz.sheepstar.global.api.models;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class RoomManager extends SheepManager {
+
+ @Override
+ protected String tableName() {
+ return "global_rooms";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("code").type(SQLType.VARCHAR).length(10).add();
+ custom("name").type(SQLType.VARCHAR).length(25).add();
+ custom("category").type(SQLType.VARCHAR).length(10).add();
+ custom("private").type(SQLType.INTEGER).length(1).defaultValue("0").add();
+ }
+
+ /**
+ * Checks if a room exists
+ *
+ * @param code The code of the room you want to check
+ * @return true
if the room exists, otherwise false
+ */
+ public boolean exists(String code) {
+ return containsRow("code", code);
+ }
+
+ /**
+ * Creates a new public room
+ *
+ * @param code The code of the room
+ * @param name The name of the room
+ * @param category The category of the room
+ */
+ public void createPublic(String code, String name, String category) {
+ if (exists(code)) return;
+ insert().value("code", code).value("name", name).value("category", category).value("private", 0).execute();
+ }
+
+ /**
+ * Creates a private room
+ *
+ * @param code The code of the room
+ */
+ public void createPrivate(String code) {
+ if (exists(code)) return;
+ insert().value("code", code).value("name", "room").value("category", "0").value("private", 1).execute();
+ }
+
+ /**
+ * Sets a room private
+ *
+ * @param code The code of the room
+ */
+ public void setPrivate(String code) {
+ updateString("code", code, "private", 1);
+ }
+
+ /**
+ * Sets a room public
+ *
+ * @param code The code of the room
+ */
+ public void setPublic(String code) {
+ updateString("code", code, "private", 0);
+ }
+
+ /**
+ * Changes the category of the provided room
+ *
+ * @param code The code of the room
+ * @param toCategory The new category
+ */
+ public void changeCategory(String code, String toCategory) {
+ updateString("code", code, "category", toCategory);
+ }
+
+ /**
+ * Changes the name of the room
+ *
+ * @param code The code of the room
+ * @param toName The new name of the room
+ */
+ public void changeName(String code, String toName) {
+ updateString("code", code, "name", toName);
+ }
+
+ /**
+ * Deletes a room by the code
+ *
+ * @param code The code of the room you want to delete
+ */
+ public void delete(String code) {
+ if (!exists(code)) return;
+ delete("code", code);
+ }
+
+ /**
+ * Checks if the room is private
+ *
+ * @param code The code of the room you want to check
+ * @return true
if the room is private, otherwise false
+ */
+ public boolean isPrivate(String code) {
+ return select().where("code", code).getResult().getInteger("private") == 1;
+ }
+
+ /**
+ * Gets all rooms by category
+ *
+ * @param category The category you want to use
+ * @return the list of rooms
+ */
+ public ArrayList> getRoomsByCategory(String category) {
+ return select().where("category", category).getResult().getList();
+ }
+
+ /**
+ * Gets a full list of all existing rooms
+ *
+ * @return the list of all existing rooms
+ */
+ public ArrayList> getRooms() {
+ return select().getResult().getList();
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ReportManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ReportManager.java
new file mode 100644
index 0000000..7ca1b9a
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ReportManager.java
@@ -0,0 +1,64 @@
+package xyz.sheepstar.global.api.models.ban;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import net.dv8tion.jda.api.entities.User;
+import xyz.sheepstar.util.sql.SheepManager;
+
+public class ReportManager extends SheepManager {
+
+ @Override
+ protected String tableName() {
+ return "global_reports";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("userID").type(SQLType.VARCHAR).length(255).add();
+ custom("reporterID").type(SQLType.VARCHAR).length(255).add();
+ custom("reason").type(SQLType.VARCHAR).length(255).add();
+ }
+
+ /**
+ * Checks if the user has reported another user
+ *
+ * @param reporter The user you want to check
+ * @param target The target you want to check
+ * @return true
if the user has reported the target, otherwise false
+ */
+ public boolean hasReported(User reporter, User target) {
+ return select().where("reporterID", reporter.getId()).where("userID", target.getId()).getResult().getRowCount() == 1;
+ }
+
+ /**
+ * Inserts a new report into the table
+ *
+ * @param reporter The user that reported the target
+ * @param target The target that you want to report
+ * @param reason The reason why you want to report this user
+ */
+ public void insertReport(User reporter, User target, String reason) {
+ if (hasReported(reporter, target)) return;
+ insert().value("userID", target.getId()).value("reporterID", reporter.getId()).value("reason", reason).execute();
+ }
+
+ /**
+ * Deletes a report from the target
+ *
+ * @param target The target you want to delete the report from
+ */
+ public void deleteReport(User target) {
+ delete("userID", target.getId());
+ }
+
+ /**
+ * Gets the reason why the target has been reported by a user
+ *
+ * @param reporter The user you want to check
+ * @param target The target you want to check
+ * @return the reason why the target has been reported
+ */
+ public String getReportReason(User reporter, User target) {
+ return select().where("reporterID", reporter.getId()).where("userID", target.getId()).getResult().getString("reason");
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ServerBanLogManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ServerBanLogManager.java
new file mode 100644
index 0000000..0d79e84
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ServerBanLogManager.java
@@ -0,0 +1,60 @@
+package xyz.sheepstar.global.api.models.ban;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import net.dv8tion.jda.api.entities.Guild;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class ServerBanLogManager extends SheepManager {
+
+ @Override
+ protected String tableName() {
+ return "global_banned_server_log";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("guildID").type(SQLType.VARCHAR).length(255).add();
+ custom("reason").type(SQLType.VARCHAR).length(999).defaultValue("No reason provided").add();
+ }
+
+ /**
+ * Inserts a ban log into the table
+ *
+ * @param guild The guild you want to insert
+ */
+ public void insertLog(Guild guild) {
+ insert().value("guildID", guild.getId()).execute();
+ }
+
+ /**
+ * Inserts a ban log into the table
+ *
+ * @param guild The guild you want to insert
+ * @param reason The reason why you banned the guild
+ */
+ public void insertLog(Guild guild, String reason) {
+ insert().value("guildID", guild.getId()).value("reason", reason).execute();
+ }
+
+ /**
+ * Gets the banned info from the table by a guild
+ *
+ * @param guild The guild you want to get the info from
+ * @return the ban infos
+ */
+ public ArrayList> getInfo(Guild guild) {
+ return select().where("guildID", guild).getResult().getList();
+ }
+
+ /**
+ * Clears the ban-log of a guild
+ *
+ * @param guild The guild you want to clear the log from
+ */
+ public void clearLog(Guild guild) {
+ delete("guildID", guild.getId());
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ServerBanManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ServerBanManager.java
new file mode 100644
index 0000000..34ceffa
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ServerBanManager.java
@@ -0,0 +1,72 @@
+package xyz.sheepstar.global.api.models.ban;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import net.dv8tion.jda.api.entities.Guild;
+import xyz.sheepstar.util.sql.SheepManager;
+
+public class ServerBanManager extends SheepManager {
+
+ @Override
+ protected String tableName() {
+ return "global_banned_servers";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("guildID").type(SQLType.VARCHAR).length(255).add();
+ custom("reason").type(SQLType.VARCHAR).length(999).defaultValue("No reason provided").add();
+ }
+
+ /**
+ * Checks if a guild is banned
+ *
+ * @param guild The guild you want to check
+ * @return true
if the guild is banned, otherwise false
+ */
+ public boolean isBanned(Guild guild) {
+ return containsRow("guildID", guild.getId());
+ }
+
+ /**
+ * Bans a guild from the global chat
+ *
+ * @param guild The guild you want to ban
+ */
+ public void ban(Guild guild) {
+ if (isBanned(guild)) return;
+ insert().value("guildID", guild.getId()).execute();
+ }
+
+ /**
+ * Bans a guild from the global chat with a reason
+ *
+ * @param guild The guild you want to ban
+ * @param reason The reason why you want to ban the guild
+ */
+ public void ban(Guild guild, String reason) {
+ if (isBanned(guild)) return;
+ insert().value("guildID", guild.getId()).value("reason", reason).execute();
+ }
+
+ /**
+ * Unbans a guild from the global chat
+ *
+ * @param guild The guild you want to unban
+ */
+ public void unban(Guild guild) {
+ if (!isBanned(guild)) return;
+ delete("guildID", guild.getId());
+ }
+
+ /**
+ * Gets the reason why a guild is banned
+ *
+ * @param guild The guild you want to check
+ * @return the ban reason
+ */
+ public String getReason(Guild guild) {
+ if (!isBanned(guild)) return "Guild is not banned";
+ return getString("guildID", guild.getId(), "reason");
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/UserBanLogManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/UserBanLogManager.java
new file mode 100644
index 0000000..cd67259
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/UserBanLogManager.java
@@ -0,0 +1,60 @@
+package xyz.sheepstar.global.api.models.ban;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import net.dv8tion.jda.api.entities.User;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class UserBanLogManager extends SheepManager {
+ @Override
+ protected String tableName() {
+ return "global_banned_user_log";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("clientID").type(SQLType.VARCHAR).length(255).add();
+ custom("reason").type(SQLType.VARCHAR).length(999).defaultValue("No reason provided").add();
+ }
+
+ /**
+ * Inserts a ban log into the table
+ *
+ * @param user The user you want to insert
+ */
+ public void insertLog(User user) {
+ insert().value("clientID", user.getId()).execute();
+ }
+
+ /**
+ * Inserts a ban log into the table
+ *
+ * @param user The user you want to insert
+ * @param reason The reason why you want to insert the user
+ */
+ public void insertLog(User user, String reason) {
+ insert().value("clientID", user.getId()).value("reason", reason).execute();
+ }
+
+ /**
+ * Gets the info about a user
+ *
+ * @param user The user you want to get the info from
+ * @return the list of bans the user had
+ */
+ public ArrayList> getInfo(User user) {
+ return select().where("clientID", user).getResult().getList();
+ }
+
+ /**
+ * Clears the user ban log
+ *
+ * @param user The user you want to clear the log from
+ */
+ public void clearLog(User user) {
+ delete("guildID", user.getId());
+ }
+
+}
\ No newline at end of file
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/UserBanManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/UserBanManager.java
new file mode 100644
index 0000000..2d81ca6
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/UserBanManager.java
@@ -0,0 +1,72 @@
+package xyz.sheepstar.global.api.models.ban;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import net.dv8tion.jda.api.entities.User;
+import xyz.sheepstar.util.sql.SheepManager;
+
+public class UserBanManager extends SheepManager {
+
+ @Override
+ protected String tableName() {
+ return "global_banned_users";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("clientID").type(SQLType.VARCHAR).length(255).add();
+ custom("reason").type(SQLType.VARCHAR).length(999).defaultValue("No reason provided").add();
+ }
+
+ /**
+ * Checks if a user has been banned
+ *
+ * @param user The user you want to check
+ * @return true
if the user is banned, otherwise false
+ */
+ public boolean isBanned(User user) {
+ return containsRow("clientID", user.getId());
+ }
+
+ /**
+ * Bans a user from the global chat
+ *
+ * @param user The user you want to ban
+ */
+ public void ban(User user) {
+ if (isBanned(user)) return;
+ insert().value("clientID", user.getId()).execute();
+ }
+
+ /**
+ * Bans a user from the global chat with a reason
+ *
+ * @param user The user you want to ban
+ * @param reason The reason why you want to ban the user
+ */
+ public void ban(User user, String reason) {
+ if (isBanned(user)) return;
+ insert().value("clientID", user.getId()).value("reason", reason).execute();
+ }
+
+ /**
+ * Unbans a user from the global chat
+ *
+ * @param user The user you want to unban
+ */
+ public void unban(User user) {
+ if (!isBanned(user)) return;
+ delete("clientID", user.getId());
+ }
+
+ /**
+ * Gets the reason why the user is currently banned
+ *
+ * @param user The user you want to check
+ * @return the reason why the user is banned
+ */
+ public String getReason(User user) {
+ if (!isBanned(user)) return "User is not banned";
+ return getString("clientID", user.getId(), "reason");
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/EmotePackManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/EmotePackManager.java
new file mode 100644
index 0000000..bdabfbe
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/EmotePackManager.java
@@ -0,0 +1,119 @@
+package xyz.sheepstar.global.api.models.emote;
+
+import net.dv8tion.jda.api.entities.Emote;
+import net.dv8tion.jda.api.entities.Guild;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.TreeMap;
+
+public class EmotePackManager extends SheepManager {
+
+
+ private final HashMap> packCache = new HashMap<>();
+
+ /**
+ * Basic constructor of the {@link EmotePackManager}
+ * It initializes/updates the emote pack cache
+ */
+ public EmotePackManager() {
+ updateEmotePackCache();
+ }
+
+ /**
+ * Updates the current emote pack cache
+ */
+ public void updateEmotePackCache() {
+ packCache.clear();
+ getPacks().forEach(pack -> {
+ TreeMap emoteCache = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ api.getJDA().getGuildById((String) pack.get("pack_serverId")).getEmoteCache().forEach(emote ->
+ emoteCache.put(emote.getName().replace("D_D", ":"), emote));
+ packCache.put((String) pack.get("pack_name"), emoteCache);
+ });
+ }
+
+ @Override
+ protected String tableName() {
+ return "global_emotepacks";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom().name("pack_name").add();
+ custom().name("pack_description").add();
+ custom().name("pack_serverId").add();
+ }
+
+ /**
+ * Checks if the provided pack exists
+ *
+ * @param packName The pack you want to check
+ * @return true
if the provided pack exists, otherwise false
+ */
+ public boolean packExists(String packName) {
+ return containsRow("pack_name", packName);
+ }
+
+ /**
+ * Gets the guild from the pack
+ *
+ * @param packName The pack you want to use
+ * @return the guild
+ */
+ public Guild getGuildByPack(String packName) {
+ if (!packExists(packName)) return null;
+ return api.getJDA().getGuildById(getString("pack_name", packName, "pack_serverId"));
+ }
+
+ /**
+ * Gets the pack description
+ *
+ * @param packName The name of the pack you want to get the description from
+ * @return the pack description
+ */
+ public String getPackDescription(String packName) {
+ return getString("pack_name", packName, "pack_description");
+ }
+
+ /**
+ * Removes a pack from the table
+ *
+ * @param packName The pack you want to remove
+ */
+ public void removePack(String packName) {
+ if (!packExists(packName)) return;
+ delete().where("pack_name", packName).execute();
+ }
+
+ /**
+ * Creates a pack / inserts it to the table
+ *
+ * @param packName The pack you want to create
+ * @param packServer The server with emotes you want to use
+ * @param packDescription The description of the pack
+ */
+ public void createPack(String packName, Guild packServer, String packDescription) {
+ if (packExists(packName)) return;
+ insert().value("pack_name", packName).value("pack_serverId", packServer.getId()).value("pack_description", packDescription).execute();
+ }
+
+ /**
+ * Gets all current packs
+ *
+ * @return all current packs
+ */
+ public ArrayList> getPacks() {
+ return select().getResult().getList();
+ }
+
+ /**
+ * Gets the current pack cache
+ *
+ * @return the current pack cache
+ */
+ public HashMap> getPackCache() {
+ return packCache;
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/EnabledEmotePackManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/EnabledEmotePackManager.java
new file mode 100644
index 0000000..89db282
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/EnabledEmotePackManager.java
@@ -0,0 +1,91 @@
+package xyz.sheepstar.global.api.models.emote;
+
+import net.dv8tion.jda.api.entities.Emote;
+import net.dv8tion.jda.api.entities.Guild;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class EnabledEmotePackManager extends SheepManager {
+
+ private final EmotePackManager emotePackManager = (EmotePackManager) table(EmotePackManager.class);
+
+ @Override
+ protected String tableName() {
+ return "global_enabled_emotepacks";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom().name("guildID").add();
+ custom().name("emotepack").add();
+ }
+
+ /**
+ * Checks if the provided guild uses the provided pack
+ *
+ * @param guild The guild you want to check
+ * @param emotepack The pack you want to check
+ * @return true
if the guild uses the pack, otherwise false
+ */
+ public boolean usesPack(Guild guild, String emotepack) {
+ return select().where("guildID", guild.getId()).where("emotepack", emotepack).getResult().exists();
+ }
+
+ /**
+ * Enables a pack
+ *
+ * @param guild The guild you want to use
+ * @param emotepack The pack you want to enable
+ */
+ public void enablePack(Guild guild, String emotepack) {
+ if (usesPack(guild, emotepack)) return;
+ insert().value("guildID", guild.getId()).value("emotepack", emotepack).execute();
+ }
+
+ /**
+ * Disables a pack
+ *
+ * @param guild The guild you want to use
+ * @param emotepack The pack you want to disable
+ */
+ public void disablePack(Guild guild, String emotepack) {
+ if (!usesPack(guild, emotepack)) return;
+ delete().where("guildID", guild.getId()).where("emotepack", emotepack).execute();
+ }
+
+ /**
+ * Lists all used pack from a guild
+ *
+ * @param guild The guild you want to get the packs from
+ * @return the list of all used packs from a guild
+ */
+ public ArrayList usedPacks(Guild guild) {
+ return select().where("guildID", guild.getId()).getResult().getList("emotepack");
+ }
+
+ /**
+ * Replaces all emotes in a message using the emote packs from a guild
+ *
+ * @param guild The guild you want to get the emote packs from
+ * @param messageText The message you want to replace
+ * @return the message with filled in emotes
+ */
+ public String replaceEmotes(Guild guild, String messageText) {
+ AtomicReference message = new AtomicReference<>(messageText);
+ usedPacks(guild).forEach(pack -> {
+ if (usesPack(guild, pack)) {
+ TreeMap packEmotes = emotePackManager.getPackCache().get(pack);
+ Arrays.stream(messageText.split(" ")).forEach(word -> {
+ if (packEmotes.containsKey(word))
+ message.set(message.get().replace(word, packEmotes.get(word).getAsMention()));
+ });
+ }
+ });
+ return message.toString();
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/GlobalEmoteManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/GlobalEmoteManager.java
new file mode 100644
index 0000000..2cfb245
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/GlobalEmoteManager.java
@@ -0,0 +1,88 @@
+package xyz.sheepstar.global.api.models.emote;
+
+import net.dv8tion.jda.api.entities.Emote;
+import xyz.sheepstar.core.SheepstarCore;
+import xyz.sheepstar.util.Sheepstar;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class GlobalEmoteManager {
+
+ private final Map emoteCache = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+
+ private final String emoteServerID = "858740877919780874";
+
+ private final Sheepstar api = SheepstarCore.getSheepstar();
+
+ /**
+ * Basic constructor of the {@link GlobalEmoteManager}
+ * It initializes/updates the current emote cache
+ */
+ public GlobalEmoteManager() {
+ updateEmoteCache();
+ }
+
+ /**
+ * Checks if the current emote cache is empty
+ *
+ * @return true
if the emote cache is empty, otherwise false
+ */
+ public boolean isCacheEmpty() {
+ return emoteCache.isEmpty();
+ }
+
+ /**
+ * Updates the current emote cache
+ */
+ public void updateEmoteCache() {
+ emoteCache.clear();
+ api.getJDA().getGuildById(emoteServerID).getEmotes().forEach(emote -> emoteCache.put(emote.getName().replace("D_D", ":"), emote));
+ }
+
+ /**
+ * Gets the current emote cache
+ *
+ * @return the current emote cache
+ */
+ public Map getEmoteCache() {
+ return emoteCache;
+ }
+
+ /**
+ * Get one emote from the emote cache
+ *
+ * @param emoteName The emote you want to get
+ * @return the emote from the emote cache
+ */
+ public Emote getFromCache(String emoteName) {
+ return emoteCache.get(emoteName);
+ }
+
+ /**
+ * Replaces all emotes from the list in the message
+ *
+ * @param messageText The message you want to use / replace
+ * @return the new message with prefilled emotes
+ */
+ public String replaceEmotes(String messageText) {
+ AtomicReference newMessage = new AtomicReference<>(messageText);
+ Arrays.stream(messageText.split(" ")).forEach(word -> {
+ if (emoteCache.containsKey(word))
+ newMessage.set(newMessage.get().replace(word, emoteCache.get(word).getAsMention()));
+ });
+ return newMessage.get();
+ }
+
+ /**
+ * Gets the current count of emotes
+ *
+ * @return the current count of emotes
+ */
+ public int getEmoteCount() {
+ return emoteCache.size();
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/log/LogManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/log/LogManager.java
new file mode 100644
index 0000000..35a35ea
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/log/LogManager.java
@@ -0,0 +1,105 @@
+package xyz.sheepstar.global.api.models.log;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.Message;
+import net.dv8tion.jda.api.entities.User;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class LogManager extends SheepManager {
+
+ @Override
+ protected String tableName() {
+ return "global_log";
+ }
+
+ @Override
+ protected void tableFields() {
+ string("guildID", 25, false, "");
+ string("clientID", 25, false, "");
+ string("messageID", 25, false, "");
+ string("message", 5000, false, "");
+ custom("date").length(6).type(SQLType.TIMESTAMP).allowNull(true).extras(new String[]{"DEFAULT CURRENT_TIMESTAMP(6)"}).add();
+ }
+
+ /**
+ * Inserts a new message into the log
+ *
+ * @param guild The guild that sent the message
+ * @param user The user that sent the message
+ * @param message The message you want to insert
+ */
+ public void insertLog(Guild guild, User user, Message message, String msgContent) {
+ insert().value("guildID", guild.getId())
+ .value("clientID", user.getId())
+ .value("messageID", message.getId())
+ .value("message", msgContent).execute();
+ }
+
+ public void delete(String messageID) {
+ delete().where("messageID", messageID).execute();
+ }
+
+ /**
+ * Gets the current log
+ *
+ * @return the current log
+ */
+ public ArrayList> getLog() {
+ return select().getResult().getList();
+ }
+
+ /**
+ * Gets the current user log
+ *
+ * @param user The user you want to get the log from
+ * @return the current user log
+ */
+ public ArrayList> getUserLog(User user) {
+ return select().where("clientID", user.getId()).getResult().getList();
+ }
+
+ /**
+ * Gets the current guild log
+ *
+ * @param guild The guild you want to get the log from
+ * @return the current guild log
+ */
+ public ArrayList> getGuildLog(Guild guild) {
+ return select().where("guildID", guild.getId()).getResult().getList();
+ }
+
+ /**
+ * Gets the written messages by regex
+ *
+ * @param message The message you want to check
+ * @return the list of messages
+ */
+ public ArrayList> getMessages(String message) {
+ return api.getDatabase().getResult("SELECT * from global_log WHERE message REGEXP ? ORDER BY id DESC", message).getList();
+ }
+
+ /**
+ * Gets the guild id from the provided message id
+ *
+ * @param message The message id
+ * @return the guild id
+ */
+ public String getGuildIdFromMessage(String message) {
+ return select().where("messageID", message).getResult().getString("guildID");
+ }
+
+ /**
+ * Gets the client id from the provided message id
+ *
+ * @param message The message id
+ * @return the client id
+ */
+ public String getClientIdFromMessage(String message) {
+ return select().where("messageID", message).getResult().getString("clientID");
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/log/OriginalLogManager.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/log/OriginalLogManager.java
new file mode 100644
index 0000000..c93cf8f
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/log/OriginalLogManager.java
@@ -0,0 +1,94 @@
+package xyz.sheepstar.global.api.models.log;
+
+import de.gnmyt.sqltoolkit.types.SQLType;
+import xyz.sheepstar.util.sql.SheepManager;
+
+import java.util.HashMap;
+
+public class OriginalLogManager extends SheepManager {
+
+ @Override
+ protected String tableName() {
+ return "global_original_log";
+ }
+
+ @Override
+ protected void tableFields() {
+ custom("originID").add();
+ custom("channelID").add();
+ custom("messageID").add();
+ custom("date").length(6).type(SQLType.TIMESTAMP).allowNull(true).extras(new String[]{"DEFAULT CURRENT_TIMESTAMP(6)"}).add();
+ }
+
+ /**
+ * Inserts a new log entry
+ *
+ * @param originID The origin ID
+ * @param channelID The channel ID
+ * @param messageID The message ID
+ */
+ public void insert(String originID, String channelID, String messageID) {
+ insert().value("originID", originID).value("channelID", channelID).value("messageID", messageID).execute();
+ }
+
+ /**
+ * Returns a list of all origins
+ *
+ * @param originID The origin ID
+ * @return a list of all origins
+ */
+ public HashMap getAllIds(String originID) {
+ return select().where("originID", originID).getResult().getMultipleList("channelID", "messageID");
+ }
+
+ /**
+ * Deletes all entries for a channel message
+ *
+ * @param messageID The message ID
+ * @return true
if the deletion was successful, otherwise false
+ */
+ public boolean existsOrigin(String messageID) {
+ return select().where("messageID", messageID).getResult().exists();
+ }
+
+ /**
+ * Finds an origin by the message id
+ *
+ * @param messageID The message ID
+ * @return the origin ID
+ */
+ public String findOrigin(String messageID) {
+ return select().where("messageID", messageID).getResult().getString("originID");
+ }
+
+ /**
+ * Finds an origin by the message id
+ *
+ * @param originID The origin ID
+ * @param channelID The channel ID
+ * @return the message ID
+ */
+ public String findMessage(String originID, String channelID) {
+ return select().where("originID", originID).where("channelID", channelID).getResult().getString("messageID");
+ }
+
+ /**
+ * Deletes all entries for a channel message
+ *
+ * @param originID The origin ID
+ */
+ public void delete(String originID) {
+ delete().where("originID", originID).execute();
+ }
+
+ /**
+ * Deletes all entries for a channel message
+ *
+ * @param originID The origin ID
+ * @param messageID The message ID
+ */
+ public void delete(String originID, String messageID) {
+ delete().where("originID", originID).where("messageID", messageID).execute();
+ }
+
+}
\ No newline at end of file
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/EmotePackCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/EmotePackCommand.java
new file mode 100644
index 0000000..0cef21e
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/EmotePackCommand.java
@@ -0,0 +1,64 @@
+package xyz.sheepstar.global.commands;
+
+import com.google.common.base.CaseFormat;
+import net.dv8tion.jda.api.entities.Emote;
+import xyz.sheepstar.global.api.models.emote.EmotePackManager;
+import xyz.sheepstar.global.api.models.emote.EnabledEmotePackManager;
+import xyz.sheepstar.util.bot.builder.message.DefaultResponseBuilder;
+import xyz.sheepstar.util.bot.builder.message.MessageType;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildCommand;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+import xyz.sheepstar.util.http.client.entities.Article;
+import xyz.sheepstar.util.http.client.objects.ArticleObject;
+import xyz.sheepstar.util.http.client.objects.ShopObject;
+
+@CommandMeta(aliases = "global", subAliases = {"emotepack", "emotepacks", "emotep"},
+ description = "Enables/Disables a emotepack", permission = PermissionNode.ADMINISTRATOR,
+ requiredSetting = "send_emotes")
+public class EmotePackCommand extends GuildCommand {
+
+ private final EmotePackManager emotePackManager = (EmotePackManager) table(EmotePackManager.class);
+ private final EnabledEmotePackManager enabledEmotePackManager = (EnabledEmotePackManager) table(EnabledEmotePackManager.class);
+ private final ShopObject itemManager = api.getShop();
+ private final ArticleObject articleManager = api.getArticles();
+
+ @Override
+ public void usage() {
+ usage("name", "The name of the emote pack you want to enable/disable").add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ if (!args.exists("name")) {
+ DefaultResponseBuilder message = event.custom(MessageType.PRIMARY)
+ .withTitle(translate("global.emote_pack_info.title", event.getLanguage()));
+
+ emotePackManager.getPacks().forEach(pack ->
+ message.addField(emotePackManager.getPackCache().get((String) pack.get("pack_name")).values().toArray(new Emote[]{})[0]
+ .getAsMention() + " " + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, (String) pack.get("pack_name")),
+ translate((String) pack.get("pack_description"), event.getGuild())));
+
+ message.send();
+ } else {
+ Article article = articleManager.findArticle("global", args.getString("name").toLowerCase() + "_emotepack").complete();
+
+ if (article == null)
+ throw new PublicCommandException("global.emote_pack.not_found");
+
+ if (!itemManager.hasItem(article.getID() + "", event.getGuild()).complete())
+ throw new PublicCommandException("bot.item.not_owned");
+
+ if (enabledEmotePackManager.usesPack(event.getGuild(), args.getString("name").toLowerCase())) {
+ enabledEmotePackManager.disablePack(event.getGuild(), args.getString("name").toLowerCase());
+ event.success("global.pack_disabled", CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, args.getString("name")));
+ } else {
+ enabledEmotePackManager.enablePack(event.getGuild(), args.getString("name").toLowerCase());
+ event.success("global.pack_enabled", CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, args.getString("name")));
+ }
+ }
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ListEmotesCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ListEmotesCommand.java
new file mode 100644
index 0000000..35bfa63
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ListEmotesCommand.java
@@ -0,0 +1,38 @@
+package xyz.sheepstar.global.commands;
+
+import net.dv8tion.jda.api.entities.Emote;
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.global.api.models.emote.EmotePackManager;
+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.Map;
+
+@CommandMeta(aliases = "global", subAliases = {"emotes", "listemotes"}, description = "Lists all emotes you can use in a global channel",
+ requiredSetting = "send_emotes")
+public class ListEmotesCommand extends GlobalCommand {
+
+ private final EmotePackManager emotePackManager = (EmotePackManager) table(EmotePackManager.class);
+
+ @Override
+ public void usage() {
+ usage("name", "The name of the emote pack").add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ StringBuilder description = new StringBuilder();
+
+ Map emoteCache = args.exists("name") ? emotePackManager.getPackCache().get(args.getString("name"))
+ : getEmoteManager().getEmoteCache();
+
+ emoteCache.forEach((name, emote) -> {
+ if (!description.toString().isEmpty()) description.append("\n");
+ description.append(String.format("%s | `%s`", emote.getAsMention(), name));
+ });
+
+
+ event.primary("global.emote_list", description.toString());
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/LogCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/LogCommand.java
new file mode 100644
index 0000000..04c6228
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/LogCommand.java
@@ -0,0 +1,82 @@
+package xyz.sheepstar.global.commands;
+
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.User;
+import xyz.sheepstar.global.api.GlobalCommand;
+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.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+
+@CommandMeta(aliases = "globalmod", subAliases = {"log", "viewlog"}, permission = PermissionNode.SUPPORTER,
+ description = "Shows you the log of messages")
+public class LogCommand extends GlobalCommand {
+
+ @Override
+ public void usage() {
+ usage("userID", "Use this option if you want to search the log by a user").add();
+ usage("guildID", "Use this option if you want to search the log by a guild").add();
+ usage("text", "Use this option if you want to search the log by text").add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ StringBuilder content = new StringBuilder();
+ if (args.exists("userID")) {
+ User user = null;
+ try {
+ user = args.retrieveUser("userID");
+ } catch (Exception e) {
+ }
+
+ if (user == null) throw new PublicCommandException("global.error.user_does_not_exist");
+
+ getLogManager().getUserLog(user).forEach(entry -> {
+ if (!content.toString().isEmpty()) content.append("\n");
+ content.append(String.format("`%s`", entry.get("message")));
+ });
+
+ event.custom(MessageType.PRIMARY)
+ .withTitle(translate("global.user_log", event.getLanguage(), user.getAsTag()))
+ .withDescription((content.toString().length() > 2000) ? content.substring(0, 2000) : content.toString())
+ .send();
+
+ } else if (args.exists("guildID")) {
+ Guild guild = null;
+
+ try {
+ guild = jda.getGuildById(args.getString("guildID"));
+ } catch (Exception e) {
+ }
+
+ if (guild == null) throw new PublicCommandException("global.error.guild_does_not_exist");
+
+ getLogManager().getGuildLog(guild).forEach(entry -> {
+ if (!content.toString().isEmpty()) content.append("\n");
+ content.append(String.format("`%s`", entry.get("message")));
+ });
+
+ event.custom(MessageType.PRIMARY)
+ .withTitle(translate("global.guild_log", event.getLanguage(), guild.getName()))
+ .withDescription((content.toString().length() > 2000) ? content.substring(0, 2000) : content.toString())
+ .send();
+
+ } else if (args.exists("text")) {
+ getLogManager().getMessages(args.getString("text")).forEach(entry -> {
+ if (!content.toString().isEmpty()) content.append("\n");
+ content.append(String.format("`%s` | user: `%s` | guild: `%s`",
+ entry.get("message").toString().length() > 20 ? entry.get("message")
+ .toString().substring(0, Math.min(entry.get("message").toString().length(), 20)) + "..."
+ : entry.get("message"),
+ entry.get("clientID"), entry.get("guildID")));
+ });
+
+ event.custom(MessageType.PRIMARY)
+ .withTitle(translate("global.text_log", event.getLanguage()))
+ .withDescription((content.toString().length() > 2000) ? content.substring(0, 2000) : content.toString())
+ .send();
+ }
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/RulesCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/RulesCommand.java
new file mode 100644
index 0000000..f7ccc60
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/RulesCommand.java
@@ -0,0 +1,17 @@
+package xyz.sheepstar.global.commands;
+
+import xyz.sheepstar.global.api.GlobalCommand;
+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.permission.PermissionNode;
+
+@CommandMeta(aliases = "global", subAliases = {"rules", "rule", "r"},
+ permission = PermissionNode.ADMINISTRATOR, description = "Shows you the rules of the global chat")
+public class RulesCommand extends GlobalCommand {
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ event.primary("global.rules");
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/BanServerCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/BanServerCommand.java
new file mode 100644
index 0000000..431f573
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/BanServerCommand.java
@@ -0,0 +1,43 @@
+package xyz.sheepstar.global.commands.ban;
+
+import net.dv8tion.jda.api.entities.Guild;
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+
+
+@CommandMeta(aliases = "globalmod", subAliases = {"banserver", "serverban"}, permission = PermissionNode.SUPPORTER,
+ description = "Bans a server from the global chat")
+public class BanServerCommand extends GlobalCommand {
+
+ @Override
+ public void usage() {
+ usage("guildID", "The id of the guild you want to ban").required(true).add();
+ usage("reason", "The reason why you want to ban this guild").add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ Guild guild = null;
+
+ try {
+ guild = jda.getGuildById(args.getString("guildID"));
+ } catch (Exception ignored) {
+ }
+
+ if (guild == null) throw new PublicCommandException("global.error.guild_does_not_exist");
+
+ if (getServerBanManager().isBanned(guild))
+ throw new PublicCommandException("global.error.guild_already_banned");
+
+ String message = args.exists("reason") ? args.getString("reason") : "No reason provided";
+
+ getServerBanManager().ban(guild, message);
+ getServerBanLogManager().insertLog(guild, message);
+
+ event.success("global.guild_banned_successfully", getServerBanManager().getReason(guild));
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/BanUserCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/BanUserCommand.java
new file mode 100644
index 0000000..8cda935
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/BanUserCommand.java
@@ -0,0 +1,38 @@
+package xyz.sheepstar.global.commands.ban;
+
+import net.dv8tion.jda.api.entities.User;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+
+
+@CommandMeta(aliases = "globalmod", subAliases = {"banuser", "userban"}, permission = PermissionNode.SUPPORTER,
+ description = "Bans a specific user from the global chat")
+public class BanUserCommand extends GlobalCommand {
+
+ @Override
+ public void usage() {
+ usage(OptionType.USER, "user", "The user you want to ban").required(true).add();
+ usage("reason", "The reason why you want to ban this user").add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ User user = args.retrieveUser("user");
+
+ if (user == null) throw new PublicCommandException("global.error.user_does_not_exist");
+
+ if (getUserBanManager().isBanned(user)) throw new PublicCommandException("global.error.user_already_banned");
+
+ String message = args.exists("reason") ? args.getString("reason") : "No reason provided";
+
+ getUserBanManager().ban(user, message);
+ getUserBanLogManager().insertLog(user, message);
+
+ event.success("global.user_banned_successfully", user.getAsTag(), getUserBanManager().getReason(user));
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/ReportCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/ReportCommand.java
new file mode 100644
index 0000000..6368cf2
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/ReportCommand.java
@@ -0,0 +1,32 @@
+package xyz.sheepstar.global.commands.ban;
+
+import net.dv8tion.jda.api.entities.User;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+
+@CommandMeta(aliases = "global", subAliases = {"report", "reportuser"}, description = "Reports a user in the global chat")
+public class ReportCommand extends GlobalCommand {
+
+ @Override
+ public void usage() {
+ usage(OptionType.USER, "user", "The user you want to report").required(true).add();
+ usage("reason", "The reason why you want to report this user").required(true).add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ User target = args.getUser("user");
+ if (target == null) throw new PublicCommandException("global.error.user_does_not_exist");
+
+ if (getReportManager().hasReported(event.getAuthor(), target))
+ throw new PublicCommandException("global.report.already_reported");
+
+ getReportManager().insertReport(event.getAuthor(), target, args.getString("reason"));
+
+ event.success("global.report.user_reported", target.getAsTag());
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/UnbanServerCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/UnbanServerCommand.java
new file mode 100644
index 0000000..dca2ca3
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/UnbanServerCommand.java
@@ -0,0 +1,36 @@
+package xyz.sheepstar.global.commands.ban;
+
+import net.dv8tion.jda.api.entities.Guild;
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+
+@CommandMeta(aliases = "globalmod", subAliases = {"unbanserver", "serverunban"}, permission = PermissionNode.SUPPORTER,
+ description = "Unbans a server from the global chat")
+public class UnbanServerCommand extends GlobalCommand {
+
+ @Override
+ public void usage() {
+ usage("guildID", "The id of the guild you want to unban").required(true).add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ Guild guild = null;
+
+ try {
+ guild = jda.getGuildById(args.getString("guildID"));
+ } catch (Exception ignored) {
+ }
+
+ if (guild == null) throw new PublicCommandException("global.error.guild_does_not_exist");
+ if (!getServerBanManager().isBanned(guild)) throw new PublicCommandException("global.error.guild_not_banned");
+
+ getServerBanManager().unban(guild);
+
+ event.success("global.guild_unbanned");
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/UnbanUserCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/UnbanUserCommand.java
new file mode 100644
index 0000000..ac6f371
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/UnbanUserCommand.java
@@ -0,0 +1,33 @@
+package xyz.sheepstar.global.commands.ban;
+
+import net.dv8tion.jda.api.entities.User;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+
+@CommandMeta(aliases = "globalmod", subAliases = {"unbanuser", "userunban"}, permission = PermissionNode.SUPPORTER,
+ description = "Unbans a user from the global chat")
+public class UnbanUserCommand extends GlobalCommand {
+
+ @Override
+ public void usage() {
+ usage(OptionType.USER, "user", "The id of the user you want to unban").required(true).add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ User user = args.retrieveUser("user");
+
+ if (user == null) throw new PublicCommandException("global.error.user_does_not_exist");
+
+ if (!getUserBanManager().isBanned(user)) throw new PublicCommandException("global.error.user_not_banned");
+
+ getUserBanManager().unban(user);
+
+ event.success("global.user_unbanned", user.getAsTag());
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/design/ChangeDesignCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/design/ChangeDesignCommand.java
new file mode 100644
index 0000000..783666f
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/design/ChangeDesignCommand.java
@@ -0,0 +1,43 @@
+package xyz.sheepstar.global.commands.design;
+
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+import xyz.sheepstar.util.http.client.entities.Article;
+import xyz.sheepstar.util.http.client.objects.ArticleObject;
+import xyz.sheepstar.util.http.client.objects.ShopObject;
+
+@CommandMeta(aliases = "global", subAliases = {"design", "changedesign"}, permission = PermissionNode.ADMINISTRATOR,
+ description = "Changes the messages design of the global channel")
+public class ChangeDesignCommand extends GlobalCommand {
+
+ private final ShopObject itemManager = api.getShop();
+ private final ArticleObject articleManager = api.getArticles();
+
+ @Override
+ public void usage() {
+ usage("designID", "The id of the design you want to use").required(true).add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ if (!getGlobalManager().isRegistered(event.getChannel()))
+ throw new PublicCommandException("global.error.not_added");
+
+ Article article = articleManager.findArticle("global", "design" + args.getString("designID")).complete();
+
+ if (article == null && !args.getString("designID").equals("1"))
+ throw new PublicCommandException("global.error.design_not_found");
+
+ if (!args.getString("designID").equals("1") &&
+ !itemManager.hasItem(article.getID() + "", event.getGuild()).complete())
+ throw new PublicCommandException("bot.item.not_owned");
+
+ getGlobalManager().setDesign(event.getChannel(), args.getString("designID").toLowerCase());
+
+ event.success("global.design_updated", args.getString("designID").toLowerCase());
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/language/ChangeLanguageCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/language/ChangeLanguageCommand.java
new file mode 100644
index 0000000..854df3c
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/language/ChangeLanguageCommand.java
@@ -0,0 +1,70 @@
+package xyz.sheepstar.global.commands.language;
+
+import net.dv8tion.jda.api.entities.Emoji;
+import net.dv8tion.jda.api.interactions.components.ButtonStyle;
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.global.api.models.GlobalManager;
+import xyz.sheepstar.util.bot.builder.message.DefaultResponseBuilder;
+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.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+
+import java.util.HashMap;
+
+@CommandMeta(aliases = "global", subAliases = {"language", "lang", "changelanguage"},
+ permission = PermissionNode.ADMINISTRATOR, description = "Changes the language of the global channel")
+public class ChangeLanguageCommand extends GlobalCommand {
+
+ private final GlobalManager globalManager = getGlobalManager();
+
+ private final HashMap languages = new HashMap<>();
+
+ /**
+ * Basic constructor of the {@link ChangeLanguageCommand}
+ * Fills in the list with all languages from the bot
+ */
+ public ChangeLanguageCommand() {
+ api.getBotManager().getLanguageManager().getLanguages().forEach(language ->
+ languages.put((String) language.get("code"), Emoji.fromUnicode((String) language.get("emoji"))));
+ }
+
+ /**
+ * Sends a message with prefilled language values
+ *
+ * @param event The {@link GuildEventController} from the listeners
+ * @return a new message with prefilled values
+ */
+ public DefaultResponseBuilder sendLanguageMessage(GuildEventController event) {
+ String currentLanguage = globalManager.getLanguage(event.getChannel());
+ DefaultResponseBuilder builder = event.custom(MessageType.PRIMARY)
+ .withTitle(translate("global.language_update", event.getLanguage()));
+ languages.forEach((language, emoji) ->
+ builder.addButton(language.equals(currentLanguage) ? ButtonStyle.PRIMARY : ButtonStyle.SECONDARY, language, emoji));
+ return builder;
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ if (!getGlobalManager().isRegistered(event.getChannel()))
+ throw new PublicCommandException("global.error.not_added");
+
+ sendLanguageMessage(event)
+ .withDescription(translate("global.choose_language", event.getLanguage()))
+ .send();
+ }
+
+ @Override
+ public void buttonClick(GuildEventController event, String id) throws Exception {
+ if (!languages.containsKey(id)) throw new PublicCommandException("bot.unknown_language");
+
+ globalManager.setLanguage(event.getChannel(), id);
+
+ sendLanguageMessage(event)
+ .withDescription(translate("global.language_updated", event.getLanguage(),
+ api.getBotManager().getLanguageManager().getName(id.toLowerCase())))
+ .send();
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/AddGlobalCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/AddGlobalCommand.java
new file mode 100644
index 0000000..9456e47
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/AddGlobalCommand.java
@@ -0,0 +1,49 @@
+package xyz.sheepstar.global.commands.modify;
+
+import net.dv8tion.jda.api.entities.ChannelType;
+import net.dv8tion.jda.api.entities.GuildChannel;
+import net.dv8tion.jda.api.entities.TextChannel;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+import xyz.sheepstar.util.http.client.objects.ShopObject;
+
+@CommandMeta(aliases = "global", subAliases = {"add", "addchannel"}, permission = PermissionNode.ADMINISTRATOR,
+ description = "Transforms the channel into a global channel")
+public class AddGlobalCommand extends GlobalCommand {
+
+ private final ShopObject itemManager = api.getShop();
+
+ @Override
+ public void usage() {
+ usage(OptionType.CHANNEL, "channel", "The channel you want to transform").add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ GuildChannel channel = args.exists("channel") ? args.getChannel("channel") : event.getChannel();
+
+ if (channel.getType() != ChannelType.TEXT)
+ throw new PublicCommandException("global.error.channel.must_be_text");
+
+ if (getGlobalManager().isRegistered((TextChannel) channel))
+ throw new PublicCommandException("global.error.already_added");
+
+ if (api.getTriggerValidator().isTriggered(channel.getId()))
+ throw new PublicCommandException("bot.error.triggers_other_module");
+
+ int currentCount = getGlobalManager().getChannelCount(event.getGuild());
+ int maxCount = itemManager.hasPremium(event.getGuild()).complete() ? 10
+ : itemManager.getItems("2", event.getGuild()).complete().size() + 2;
+
+ if (currentCount >= maxCount) throw new PublicCommandException("global.channel.limit_reached");
+
+ getGlobalManager().register((TextChannel) channel, getLanguage(event.getGuild()));
+
+ event.primary("global.welcome");
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/ClearGlobalCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/ClearGlobalCommand.java
new file mode 100644
index 0000000..d9ada80
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/ClearGlobalCommand.java
@@ -0,0 +1,18 @@
+package xyz.sheepstar.global.commands.modify;
+
+import xyz.sheepstar.global.api.GlobalCommand;
+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.permission.PermissionNode;
+
+@CommandMeta(aliases = "global", subAliases = {"clear", "clearlist", "clearchannel"},
+ permission = PermissionNode.ADMINISTRATOR, description = "Removes all global channel")
+public class ClearGlobalCommand extends GlobalCommand {
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ getGlobalManager().clearList(event.getGuild());
+ event.success("global.channels.cleared");
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/RemoveGlobalCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/RemoveGlobalCommand.java
new file mode 100644
index 0000000..faf97e0
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/RemoveGlobalCommand.java
@@ -0,0 +1,38 @@
+package xyz.sheepstar.global.commands.modify;
+
+import net.dv8tion.jda.api.entities.ChannelType;
+import net.dv8tion.jda.api.entities.GuildChannel;
+import net.dv8tion.jda.api.entities.TextChannel;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+
+@CommandMeta(aliases = "global", subAliases = {"remove", "delete", "rm"}, permission = PermissionNode.ADMINISTRATOR,
+ description = "Removes the global channel")
+public class RemoveGlobalCommand extends GlobalCommand {
+
+ @Override
+ public void usage() {
+ usage(OptionType.CHANNEL, "channel", "The channel you want to remove").add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+
+ GuildChannel channel = args.exists("channel") ? args.getChannel("channel") : event.getChannel();
+
+ if (channel.getType() != ChannelType.TEXT)
+ throw new PublicCommandException("global.error.channel.must_be_text");
+
+ if (!getGlobalManager().isRegistered((TextChannel) channel))
+ throw new PublicCommandException("global.error.not_added");
+
+ getGlobalManager().unregister((TextChannel) channel);
+
+ event.success("global.goodbye");
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/rooms/ChangeRoomCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/rooms/ChangeRoomCommand.java
new file mode 100644
index 0000000..2ca519a
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/rooms/ChangeRoomCommand.java
@@ -0,0 +1,35 @@
+package xyz.sheepstar.global.commands.rooms;
+
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.util.bot.command.Arguments;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+
+@CommandMeta(aliases = "global", subAliases = {"room", "changeroom", "setroom"},
+ permission = PermissionNode.ADMINISTRATOR, description = "Changes the room of the global channel")
+public class ChangeRoomCommand extends GlobalCommand {
+
+ @Override
+ public void usage() {
+ usage("roomCode", "The code of the room you want to check").required(true).add();
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ if (!getGlobalManager().isRegistered(event.getChannel()))
+ throw new PublicCommandException("global.error.not_added");
+
+ if (!getRoomManager().exists(args.getString("roomCode").toLowerCase()))
+ throw new PublicCommandException("global.room.does_not_exist");
+
+ if (args.getString("roomCode").startsWith("p") && !getRoomManager().isPrivate(args.getString("roomCode"))
+ && api.getShop().hasPremium(event.getGuild()).complete())
+ throw new PublicCommandException("bot.no_premium");
+
+ getGlobalManager().setRoom(event.getChannel(), args.getString("roomCode").toLowerCase());
+
+ event.success("global.room_changed", args.getString("roomCode").toLowerCase());
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/rooms/ShowRoomsCommand.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/rooms/ShowRoomsCommand.java
new file mode 100644
index 0000000..a781ac5
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/rooms/ShowRoomsCommand.java
@@ -0,0 +1,71 @@
+package xyz.sheepstar.global.commands.rooms;
+
+import net.dv8tion.jda.api.entities.Emoji;
+import net.dv8tion.jda.api.interactions.components.ButtonStyle;
+import xyz.sheepstar.global.api.GlobalCommand;
+import xyz.sheepstar.util.bot.builder.message.DefaultResponseBuilder;
+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.PublicCommandException;
+import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
+import xyz.sheepstar.util.bot.emote.INTERN_EMOTE;
+import xyz.sheepstar.util.bot.permission.PermissionNode;
+
+@CommandMeta(aliases = "global", subAliases = {"showrooms", "listrooms"},
+ permission = PermissionNode.ADMINISTRATOR, description = "Lists all rooms you can use")
+public class ShowRoomsCommand extends GlobalCommand {
+
+ /**
+ * Prepares a new message with prefilled room values
+ *
+ * @param event The {@link GuildEventController} from the listener
+ * @param page The page of the room
+ * @return a new message with prefilled room values
+ */
+ public DefaultResponseBuilder sendRoomMessage(GuildEventController event, String page) {
+ DefaultResponseBuilder message = event.custom(MessageType.PRIMARY)
+ .withTitle(translate("global.rooms", event.getLanguage()));
+
+ if (!page.equals("home")) {
+ String currentLanguage = getGlobalManager().getLanguage(event.getChannel());
+
+ getRoomManager().getRoomsByCategory(page).forEach(room -> {
+ int count = getGlobalManager().select()
+ .where("language", currentLanguage).where("roomID", room.get("code"))
+ .getResult().getRowCount();
+
+ message.addField(String.format("%s %s (id: %s)", getEmoteString(INTERN_EMOTE.INFO), room.get("name"),
+ room.get("code")), count + " " + translate("bot.servers", event.getGuild()));
+ });
+ } else {
+ getCategoryManager().getCategories().forEach(category ->
+ message.addField(getEmoteStringById((String) category.get("reaction")) + " " + category.get("name"),
+ (String) category.get("description")));
+ }
+
+ message.addButton(page.equals("home") ? ButtonStyle.PRIMARY : ButtonStyle.SECONDARY, "home", Emoji.fromUnicode("\uD83C\uDFE0"));
+
+ getCategoryManager().getCategories().forEach(category ->
+ runIgnored(() -> message.addButton(category.get("code").equals(page) ? ButtonStyle.PRIMARY : ButtonStyle.SECONDARY,
+ ((String) category.get("code")), Emoji.fromEmote(getEmoteById((String) category.get("reaction"))))));
+
+ return message;
+ }
+
+ @Override
+ public void execute(GuildEventController event, Arguments args) throws Exception {
+ if (!getGlobalManager().isRegistered(event.getChannel()))
+ throw new PublicCommandException("global.error.not_added");
+
+ sendRoomMessage(event, "home").send();
+ }
+
+ @Override
+ public void buttonClick(GuildEventController event, String id) throws Exception {
+ if (!getGlobalManager().isRegistered(event.getChannel()))
+ throw new PublicCommandException("global.error.not_added");
+
+ sendRoomMessage(event, id).send();
+ }
+}
\ No newline at end of file
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/core/GlobalBootstrap.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/core/GlobalBootstrap.java
new file mode 100644
index 0000000..eb3d5ab
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/core/GlobalBootstrap.java
@@ -0,0 +1,189 @@
+package xyz.sheepstar.global.core;
+
+import xyz.sheepstar.global.api.DesignManager;
+import xyz.sheepstar.global.api.GlobalValidator;
+import xyz.sheepstar.global.api.models.GlobalManager;
+import xyz.sheepstar.global.api.models.GlobalUserSlowMode;
+import xyz.sheepstar.global.api.models.RoomCategoryManager;
+import xyz.sheepstar.global.api.models.RoomManager;
+import xyz.sheepstar.global.api.models.ban.*;
+import xyz.sheepstar.global.api.models.emote.EmotePackManager;
+import xyz.sheepstar.global.api.models.emote.EnabledEmotePackManager;
+import xyz.sheepstar.global.api.models.emote.GlobalEmoteManager;
+import xyz.sheepstar.global.api.models.log.LogManager;
+import xyz.sheepstar.global.api.models.log.OriginalLogManager;
+import xyz.sheepstar.global.commands.EmotePackCommand;
+import xyz.sheepstar.global.commands.ListEmotesCommand;
+import xyz.sheepstar.global.commands.LogCommand;
+import xyz.sheepstar.global.commands.RulesCommand;
+import xyz.sheepstar.global.commands.ban.*;
+import xyz.sheepstar.global.commands.design.ChangeDesignCommand;
+import xyz.sheepstar.global.commands.language.ChangeLanguageCommand;
+import xyz.sheepstar.global.commands.modify.AddGlobalCommand;
+import xyz.sheepstar.global.commands.modify.ClearGlobalCommand;
+import xyz.sheepstar.global.commands.modify.RemoveGlobalCommand;
+import xyz.sheepstar.global.commands.rooms.ChangeRoomCommand;
+import xyz.sheepstar.global.commands.rooms.ShowRoomsCommand;
+import xyz.sheepstar.global.listeners.DeleteListener;
+import xyz.sheepstar.global.listeners.GlobalListener;
+import xyz.sheepstar.util.Sheepstar;
+import xyz.sheepstar.util.SheepstarImpl;
+import xyz.sheepstar.util.bot.manager.ImportManager;
+import xyz.sheepstar.util.module.SheepstarModule;
+
+import java.io.File;
+import java.io.IOException;
+
+public class GlobalBootstrap extends SheepstarModule {
+
+ private static Sheepstar instance;
+ private static ImportManager importManager;
+ private static GlobalEmoteManager emoteManager;
+ private static DesignManager designManager;
+
+ /**
+ * Gets the design manager
+ *
+ * @return the design manager
+ */
+ public static DesignManager getDesignManager() {
+ return designManager;
+ }
+
+ /**
+ * Gets the current sheepstar service api
+ *
+ * @return the current sheepstar service api
+ */
+ public static Sheepstar getApi() {
+ return instance;
+ }
+
+ /**
+ * Gets the emote manager
+ *
+ * @return the emote manager
+ */
+ public static GlobalEmoteManager getEmoteManager() {
+ return emoteManager;
+ }
+
+ @Override
+ public void onEnable() {
+ instance = getAPI();
+
+ registerManagers();
+ registerTables();
+
+ copyResources();
+ registerPools();
+
+ registerListeners();
+ startThreads();
+
+ instance.getTriggerValidator().createTrigger(GlobalValidator.class, new GlobalValidator());
+ }
+
+ /**
+ * Copies all resources to the correct location
+ */
+ public void copyResources() {
+ if (!new File(getDataFolder().getPath() + "/pools.json").exists()) {
+ try {
+ copyFromResource("pools.json", "pools.json");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Registers all scheduled executor pools
+ */
+ public void registerPools() {
+ loadResource("pools.json").getCurrentJsonNode().forEach(node ->
+ ((SheepstarImpl) instance).getScheduledExecutorPool().createPool(node.get("name").asText(), node.get("cores").asInt()));
+ }
+
+ /**
+ * Starts all global threads
+ */
+ public void startThreads() {
+// new ChannelDeletionProcess().start();
+ }
+
+ /**
+ * Registers all managers
+ */
+ public void registerManagers() {
+ importManager = new ImportManager(instance, "global");
+ emoteManager = new GlobalEmoteManager();
+ designManager = new DesignManager();
+ }
+
+ /**
+ * Registers all tables
+ */
+ public void registerTables() {
+ registerTable(new RoomManager());
+
+ registerTable(new GlobalManager());
+
+ registerTable(new RoomCategoryManager());
+
+ registerTable(new GlobalUserSlowMode());
+
+ registerTable(new UserBanManager());
+ registerTable(new ServerBanManager());
+
+ registerTable(new UserBanLogManager());
+ registerTable(new ServerBanLogManager());
+
+ registerTable(new OriginalLogManager());
+ registerTable(new LogManager());
+ registerTable(new ReportManager());
+
+ registerTable(new EmotePackManager());
+ registerTable(new EnabledEmotePackManager());
+ }
+
+ /**
+ * Registers all listeners
+ */
+ public void registerListeners() {
+ // Register modify commands
+ importManager.registerCommands(new AddGlobalCommand(), new RemoveGlobalCommand(), new ClearGlobalCommand());
+
+ // Register room commands
+ importManager.registerCommands(new ChangeRoomCommand(), new ShowRoomsCommand());
+
+ // Register language commands
+ importManager.registerCommands(new ChangeLanguageCommand());
+
+ // Register rule command
+ importManager.registerCommands(new RulesCommand());
+
+ // Register emote command
+ importManager.registerCommands(new ListEmotesCommand(), new EmotePackCommand());
+
+ // Register ban server commands
+ importManager.registerCommands(new BanServerCommand(), new UnbanServerCommand());
+
+ // Register user ban commands
+ importManager.registerCommands(new BanUserCommand(), new UnbanUserCommand());
+
+ // Register log command
+ importManager.registerCommands(new LogCommand());
+
+ // Register change design command
+ importManager.registerCommands(new ChangeDesignCommand());
+
+ // Register report commands
+ importManager.registerCommands(new ReportCommand());
+
+ // Register listeners
+ importManager.registerListener(new GlobalListener());
+ importManager.registerListener(new DeleteListener());
+ }
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/listeners/DeleteListener.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/listeners/DeleteListener.java
new file mode 100644
index 0000000..991d53f
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/listeners/DeleteListener.java
@@ -0,0 +1,74 @@
+package xyz.sheepstar.global.listeners;
+
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.Message;
+import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent;
+import org.jetbrains.annotations.NotNull;
+import xyz.sheepstar.global.api.models.log.LogManager;
+import xyz.sheepstar.global.api.models.log.OriginalLogManager;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.listener.GuildListener;
+
+import java.util.HashMap;
+
+public class DeleteListener extends GuildListener {
+
+ private final LogManager logManager = (LogManager) table(LogManager.class);
+ private final OriginalLogManager originalLogManager = (OriginalLogManager) table(OriginalLogManager.class);
+
+ @Override
+ public void onGuildMessageDelete(@NotNull GuildMessageDeleteEvent event) {
+ if (!isEnabled(event.getGuild())) return;
+
+ if (!originalLogManager.existsOrigin(event.getMessageId())) return;
+
+ delete(event.getGuild(), originalLogManager.findOrigin(event.getMessageId()));
+ }
+
+ @Override
+ public void messageReceived(GuildEventController event, Message message) throws Exception {
+ if (message.getReferencedMessage() == null) return;
+
+ if (!isEnabled(event.getGuild())) return;
+
+ if (!message.getContentRaw().equals("del")) return;
+
+ Message referencedMessage = message.getReferencedMessage();
+
+ if (!originalLogManager.existsOrigin(referencedMessage.getId())) return;
+
+ String originID = originalLogManager.findOrigin(referencedMessage.getId());
+
+ if (!logManager.getClientIdFromMessage(originID).equals(message.getAuthor().getId())) return;
+
+ delete(event.getGuild(), originID);
+ }
+
+ /**
+ * Deletes the origin message from the guild
+ *
+ * @param guild The guild
+ * @param originID The origin message ID
+ */
+ public void delete(Guild guild, String originID) {
+ HashMap logIDs = originalLogManager.getAllIds(originID);
+
+ String guildID = logManager.getGuildIdFromMessage(originID);
+
+ if (guildID.equals(guild.getId())) {
+ api.getScheduledExecutorPool().executeInstant("SR-ActionPool", () -> {
+ try {
+ logIDs.forEach((channelID, logID) -> api.getJDA().getTextChannelById(channelID)
+ .retrieveMessageById(logID).queue(msg -> msg.delete().queue(m -> {
+ }, t -> {
+ }), t -> {
+ }));
+ } catch (Exception ignored) {
+ }
+ });
+
+ logManager.delete(originID);
+ originalLogManager.delete(originID);
+ }
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/listeners/GlobalListener.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/listeners/GlobalListener.java
new file mode 100644
index 0000000..54d992a
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/listeners/GlobalListener.java
@@ -0,0 +1,133 @@
+package xyz.sheepstar.global.listeners;
+
+import de.gnmyt.sqltoolkit.manager.SelectionManager;
+import net.dv8tion.jda.api.entities.Message;
+import net.dv8tion.jda.api.entities.TextChannel;
+import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
+import net.dv8tion.jda.api.requests.restaction.MessageAction;
+import xyz.sheepstar.global.api.DesignManager;
+import xyz.sheepstar.global.api.GlobalValidation;
+import xyz.sheepstar.global.api.models.GlobalManager;
+import xyz.sheepstar.global.api.models.RoomManager;
+import xyz.sheepstar.global.api.models.emote.EnabledEmotePackManager;
+import xyz.sheepstar.global.api.models.emote.GlobalEmoteManager;
+import xyz.sheepstar.global.api.models.log.LogManager;
+import xyz.sheepstar.global.api.models.log.OriginalLogManager;
+import xyz.sheepstar.global.core.GlobalBootstrap;
+import xyz.sheepstar.util.bot.command.GuildEventController;
+import xyz.sheepstar.util.bot.command.PublicCommandException;
+import xyz.sheepstar.util.bot.listener.GuildListener;
+import xyz.sheepstar.util.bot.manager.sql.SettingsManager;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+public class GlobalListener extends GuildListener {
+
+ private final SettingsManager settingsManager = api.getBotManager().getSettingsManager();
+ private final GlobalManager globalManager = (GlobalManager) table(GlobalManager.class);
+ private final GlobalEmoteManager emoteManager = GlobalBootstrap.getEmoteManager();
+ private final RoomManager roomManager = (RoomManager) table(RoomManager.class);
+ private final DesignManager designManager = GlobalBootstrap.getDesignManager();
+ private final EnabledEmotePackManager emotePackManager = (EnabledEmotePackManager) table(EnabledEmotePackManager.class);
+
+ private final OriginalLogManager originalLogManager = (OriginalLogManager) table(OriginalLogManager.class);
+
+ @Override
+ public void messageReceived(GuildEventController event, Message message) throws Exception {
+ if (event.getAuthor().isBot()) return;
+
+ if (!isEnabled(event.getGuild())) return;
+
+ api.getScheduledExecutorPool().executeInstant("SR-GlobalPreparePool", () -> runSecure(event, () -> {
+ if (!globalManager.isRegistered(event.getChannel())) return;
+
+ if (!new GlobalValidation().validate(event)) return;
+
+ sendGlobal((GuildMessageReceivedEvent) event.getEvent(),
+ globalManager.getLanguage(event.getChannel()), globalManager.getRoom(event.getChannel()));
+ }));
+ }
+
+ /**
+ * Sends the global message
+ *
+ * @param event The {@link GuildMessageReceivedEvent} from the listener
+ * @param languageCode The language code of the message sender
+ * @param roomID The room id of the message sender
+ */
+ public void sendGlobal(GuildMessageReceivedEvent event, String languageCode, String roomID) throws PublicCommandException {
+ SelectionManager query = globalManager.select().where("roomID", roomID);
+ if (!roomManager.isPrivate(roomID))
+ query.where("language", languageCode);
+
+ AtomicReference message = new AtomicReference<>(event.getMessage().getContentRaw());
+
+ // Replace the user mentions
+ event.getMessage().getMentionedUsers().forEach(user -> {
+ message.set(message.get().replace("<@!" + user.getId() + ">", "@" + user.getName()));
+ message.set(message.get().replace("<@" + user.getId() + ">", "@" + user.getName()));
+ });
+
+ // Replace the role mentions
+ event.getMessage().getMentionedRoles().forEach(role ->
+ message.set(message.get().replace(role.getAsMention(), "@" + role.getName())));
+
+ // Replace the text channel mentions
+ event.getMessage().getMentionedChannels().forEach(channel ->
+ message.set(message.get().replace(channel.getAsMention(), "#" + channel.getName())));
+
+ // Replace the "everyone" and "here" mentions
+ message.set(message.get().replaceAll("@everyone", "@everyone"));
+ message.set(message.get().replaceAll("@here", "@here"));
+
+ // Replace the voice channel mentions
+ message.set(message.get().replaceAll("<#(\\d+)>", "#channel"));
+
+ // Replace emotes in the message
+ if (settingsManager.getSettingString(event.getGuild(), "global", "send_emotes").equals("yes")) {
+ message.set(emoteManager.replaceEmotes(message.get()));
+ message.set(emotePackManager.replaceEmotes(event.getGuild(), message.get()));
+ }
+
+ // Check if message overrides the discord limit
+ if (message.get().length() >= 2000) throw new PublicCommandException("global.message.too_big");
+
+ ((LogManager) table(LogManager.class)).insertLog(event.getGuild(), event.getAuthor(), event.getMessage(), message.get());
+
+ String referenceId = event.getMessage().getReferencedMessage() != null ? event.getMessage().getReferencedMessage().getId() : null;
+
+ // Send the message to every server
+ query.getResult().getList().forEach(map -> api.getScheduledExecutorPool().executeInstant("SR-GlobalSenderPool", () ->
+ sendGlobalMessage(event, jda.getTextChannelById((String) map.get("channelID")), message.get(), event.getMessageId(), referenceId)));
+ }
+
+ /**
+ * Sends the global message to a specific channel
+ *
+ * @param event The {@link GuildMessageReceivedEvent} from the listener
+ * @param currentChannel The channel you want to send the message in
+ * @param message The message that should be sent
+ * @param originalId The id of the original message
+ * @param quotedId The id of the referenced message
+ */
+ public void sendGlobalMessage(GuildMessageReceivedEvent event, TextChannel currentChannel, String message, String originalId, String quotedId) {
+ if (currentChannel == null) return;
+ if (!isEnabled(currentChannel.getGuild())) return;
+ String design = globalManager.getDesign(currentChannel);
+
+ String quoteMessage = null;
+
+ if (quotedId != null) {
+ if (originalLogManager.existsOrigin(quotedId))
+ quoteMessage = originalLogManager.findMessage(originalLogManager.findOrigin(quotedId), currentChannel.getId());
+ }
+
+ MessageAction action = currentChannel.sendMessage(designManager.getDesign(design, event.getGuild(), event.getMember(), message));
+
+ if (quoteMessage != null)
+ action = action.referenceById(quoteMessage);
+
+ action.queue(msg ->
+ originalLogManager.insert(originalId, currentChannel.getId(), msg.getId()));
+ }
+}
diff --git a/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/threads/ChannelDeletionProcess.java b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/threads/ChannelDeletionProcess.java
new file mode 100644
index 0000000..212d951
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/threads/ChannelDeletionProcess.java
@@ -0,0 +1,24 @@
+package xyz.sheepstar.global.threads;
+
+
+import xyz.sheepstar.util.sql.SimpleDeletionProcess;
+
+public class ChannelDeletionProcess extends SimpleDeletionProcess {
+
+ @Override
+ public String tableName() {
+ return "global_channels";
+ }
+
+ @Override
+ public String tableColumn() {
+ return "channelId";
+ }
+
+ @Override
+ public boolean shouldDelete(String s) {
+ return jda.getTextChannelById(s) == null;
+ }
+
+
+}
diff --git a/SheepstarModules/GlobalV1/src/main/resources/module.yml b/SheepstarModules/GlobalV1/src/main/resources/module.yml
new file mode 100644
index 0000000..be00449
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/resources/module.yml
@@ -0,0 +1,3 @@
+main: xyz.sheepstar.global.core.GlobalBootstrap
+name: global
+author: Mathias Wagner
\ No newline at end of file
diff --git a/SheepstarModules/GlobalV1/src/main/resources/pools.json b/SheepstarModules/GlobalV1/src/main/resources/pools.json
new file mode 100644
index 0000000..54f2b45
--- /dev/null
+++ b/SheepstarModules/GlobalV1/src/main/resources/pools.json
@@ -0,0 +1,10 @@
+[
+ {
+ "name": "SR-GlobalSenderPool",
+ "cores": 16
+ },
+ {
+ "name": "SR-GlobalPreparePool",
+ "cores": 8
+ }
+]
\ No newline at end of file