From c5f1a281a0ccaea303ec607acfef47c5703b6bb0 Mon Sep 17 00:00:00 2001
From: Mathias Wagner <germannewsmaker@gmail.com>
Date: Tue, 6 Sep 2022 16:26:57 +0200
Subject: [PATCH] The sheepstar global module

---
 SheepstarModules/GlobalV1/.gitignore          |   3 +
 SheepstarModules/GlobalV1/README.md           |   2 +
 SheepstarModules/GlobalV1/pom.xml             |  24 +++
 .../sheepstar/global/api/DesignManager.java   | 135 +++++++++++++
 .../sheepstar/global/api/GlobalCommand.java   | 114 +++++++++++
 .../global/api/GlobalValidation.java          |  76 +++++++
 .../sheepstar/global/api/GlobalValidator.java |  18 ++
 .../global/api/models/GlobalManager.java      | 169 ++++++++++++++++
 .../global/api/models/GlobalUserSlowMode.java | 100 +++++++++
 .../api/models/RoomCategoryManager.java       | 116 +++++++++++
 .../global/api/models/RoomManager.java        | 133 ++++++++++++
 .../global/api/models/ban/ReportManager.java  |  64 ++++++
 .../api/models/ban/ServerBanLogManager.java   |  60 ++++++
 .../api/models/ban/ServerBanManager.java      |  72 +++++++
 .../api/models/ban/UserBanLogManager.java     |  60 ++++++
 .../global/api/models/ban/UserBanManager.java |  72 +++++++
 .../api/models/emote/EmotePackManager.java    | 119 +++++++++++
 .../models/emote/EnabledEmotePackManager.java |  91 +++++++++
 .../api/models/emote/GlobalEmoteManager.java  |  88 ++++++++
 .../global/api/models/log/LogManager.java     | 105 ++++++++++
 .../api/models/log/OriginalLogManager.java    |  94 +++++++++
 .../global/commands/EmotePackCommand.java     |  64 ++++++
 .../global/commands/ListEmotesCommand.java    |  38 ++++
 .../sheepstar/global/commands/LogCommand.java |  82 ++++++++
 .../global/commands/RulesCommand.java         |  17 ++
 .../global/commands/ban/BanServerCommand.java |  43 ++++
 .../global/commands/ban/BanUserCommand.java   |  38 ++++
 .../global/commands/ban/ReportCommand.java    |  32 +++
 .../commands/ban/UnbanServerCommand.java      |  36 ++++
 .../global/commands/ban/UnbanUserCommand.java |  33 +++
 .../commands/design/ChangeDesignCommand.java  |  43 ++++
 .../language/ChangeLanguageCommand.java       |  70 +++++++
 .../commands/modify/AddGlobalCommand.java     |  49 +++++
 .../commands/modify/ClearGlobalCommand.java   |  18 ++
 .../commands/modify/RemoveGlobalCommand.java  |  38 ++++
 .../commands/rooms/ChangeRoomCommand.java     |  35 ++++
 .../commands/rooms/ShowRoomsCommand.java      |  71 +++++++
 .../global/core/GlobalBootstrap.java          | 189 ++++++++++++++++++
 .../global/listeners/DeleteListener.java      |  74 +++++++
 .../global/listeners/GlobalListener.java      | 133 ++++++++++++
 .../threads/ChannelDeletionProcess.java       |  24 +++
 .../GlobalV1/src/main/resources/module.yml    |   3 +
 .../GlobalV1/src/main/resources/pools.json    |  10 +
 43 files changed, 2855 insertions(+)
 create mode 100644 SheepstarModules/GlobalV1/.gitignore
 create mode 100644 SheepstarModules/GlobalV1/README.md
 create mode 100644 SheepstarModules/GlobalV1/pom.xml
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/DesignManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalValidation.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/GlobalValidator.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/GlobalManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/GlobalUserSlowMode.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/RoomCategoryManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/RoomManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ReportManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ServerBanLogManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/ServerBanManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/UserBanLogManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/ban/UserBanManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/EmotePackManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/EnabledEmotePackManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/emote/GlobalEmoteManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/log/LogManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/api/models/log/OriginalLogManager.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/EmotePackCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ListEmotesCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/LogCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/RulesCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/BanServerCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/BanUserCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/ReportCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/UnbanServerCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/ban/UnbanUserCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/design/ChangeDesignCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/language/ChangeLanguageCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/AddGlobalCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/ClearGlobalCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/modify/RemoveGlobalCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/rooms/ChangeRoomCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/commands/rooms/ShowRoomsCommand.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/core/GlobalBootstrap.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/listeners/DeleteListener.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/listeners/GlobalListener.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/java/xyz/sheepstar/global/threads/ChannelDeletionProcess.java
 create mode 100644 SheepstarModules/GlobalV1/src/main/resources/module.yml
 create mode 100644 SheepstarModules/GlobalV1/src/main/resources/pools.json

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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>xyz.sheepstar</groupId>
+    <artifactId>SheepstarModule-Global</artifactId>
+    <version>1.0.0</version>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>xyz.sheepstar</groupId>
+            <artifactId>SheepstarCore</artifactId>
+            <version>beta1.0.2</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ 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 <code>true</code> if all validation checks have been passed, otherwise <code>false</code>
+     */
+    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 <code>true</code> if the string contains the provided words, otherwise <code>false</code>
+     */
+    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 <code>true</code> if the text-channel is a global channel (registered), otherwise <code>false</code>
+     */
+    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<String> 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 <code>true</code> if the provided user is registered, otherwise <code>false</code>
+     */
+    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 <code>true</code> if the provided user can write, otherwise <code>false</code>
+     */
+    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 <code>true</code> if the category exists, otherwise <code>false</code>
+     */
+    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<HashMap<String, Object>> 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 <code>true</code> if the room exists, otherwise <code>false</code>
+     */
+    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 <code>true</code> if the room is private, otherwise <code>false</code>
+     */
+    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<HashMap<String, Object>> 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<HashMap<String, Object>> 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 <code>true</code> if the user has reported the target, otherwise <code>false</code>
+     */
+    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<HashMap<String, Object>> 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 <code>true</code> if the guild is banned, otherwise <code>false</code>
+     */
+    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<HashMap<String, Object>> 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 <code>true</code> if the user is banned, otherwise <code>false</code>
+     */
+    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<String, TreeMap<String, Emote>> 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<String, Emote> 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 <code>true</code> if the provided pack exists, otherwise <code>false</code>
+     */
+    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<HashMap<String, Object>> getPacks() {
+        return select().getResult().getList();
+    }
+
+    /**
+     * Gets the current pack cache
+     *
+     * @return the current pack cache
+     */
+    public HashMap<String, TreeMap<String, Emote>> 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 <code>true</code> if the guild uses the pack, otherwise <code>false</code>
+     */
+    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<String> 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<String> message = new AtomicReference<>(messageText);
+        usedPacks(guild).forEach(pack -> {
+            if (usesPack(guild, pack)) {
+                TreeMap<String, Emote> 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<String, Emote> 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 <code>true</code> if the emote cache is empty, otherwise <code>false</code>
+     */
+    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<String, Emote> 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<String> 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<HashMap<String, Object>> 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<HashMap<String, Object>> 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<HashMap<String, Object>> 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<HashMap<String, Object>> 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<String, String> 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 <code>true</code> if the deletion was successful, otherwise <code>false</code>
+     */
+    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<String, Emote> 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<String, Emoji> 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<String, String> 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<String> 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