diff --git a/src/main/java/me/youhavetrouble/inviter/discord/DiscordInvite.java b/src/main/java/me/youhavetrouble/inviter/discord/DiscordInvite.java index b193387..52240cb 100644 --- a/src/main/java/me/youhavetrouble/inviter/discord/DiscordInvite.java +++ b/src/main/java/me/youhavetrouble/inviter/discord/DiscordInvite.java @@ -5,7 +5,6 @@ public record DiscordInvite( Long guildId, Long expiresAt ) { - public DiscordInvite { if (code == null) { throw new IllegalArgumentException("Code cannot be null"); @@ -15,14 +14,4 @@ public record DiscordInvite( } } - /** - * Checks if the invite is expired. - * The invite is considered expired if the current time is more than 5 seconds before the expiration time. - * - * @return true if the invite is expired, false otherwise - */ - public boolean isExpired() { - return System.currentTimeMillis() + 5000 > expiresAt; - } - } diff --git a/src/main/java/me/youhavetrouble/inviter/discord/DiscordInviteManager.java b/src/main/java/me/youhavetrouble/inviter/discord/DiscordInviteManager.java index 7ff76f3..7c0f03a 100644 --- a/src/main/java/me/youhavetrouble/inviter/discord/DiscordInviteManager.java +++ b/src/main/java/me/youhavetrouble/inviter/discord/DiscordInviteManager.java @@ -14,7 +14,7 @@ import java.time.temporal.ChronoUnit; public class DiscordInviteManager { private final Cache cache = Caffeine.newBuilder() - .expireAfterWrite(Duration.of(60, ChronoUnit.SECONDS)) + .expireAfterWrite(Duration.of(55, ChronoUnit.SECONDS)) .build(); private final JDA jda; @@ -26,7 +26,7 @@ public class DiscordInviteManager { @Nullable public DiscordInvite getInvite(long guildId) { DiscordInvite discordInvite = cache.getIfPresent(String.valueOf(guildId)); - if (discordInvite == null || discordInvite.isExpired()) { + if (discordInvite == null) { Guild guild = jda.getGuildById(guildId); if (guild == null) { return null; // Guild not found @@ -48,4 +48,8 @@ public class DiscordInviteManager { return discordInvite; } + public void removeFromCache(long guildId) { + cache.invalidate(String.valueOf(guildId)); + } + } diff --git a/src/main/java/me/youhavetrouble/inviter/discord/GuildSettings.java b/src/main/java/me/youhavetrouble/inviter/discord/GuildSettings.java index 94f3f67..e3d1b76 100644 --- a/src/main/java/me/youhavetrouble/inviter/discord/GuildSettings.java +++ b/src/main/java/me/youhavetrouble/inviter/discord/GuildSettings.java @@ -1,11 +1,8 @@ package me.youhavetrouble.inviter.discord; -import org.jetbrains.annotations.Nullable; - public record GuildSettings( long guildId, - boolean apiEnabled, - @Nullable String apiHostname + boolean apiEnabled ) { } diff --git a/src/main/java/me/youhavetrouble/inviter/discord/command/ApiStatusChangeCommand.java b/src/main/java/me/youhavetrouble/inviter/discord/command/ApiStatusChangeCommand.java index 87c2b83..cffe9b8 100644 --- a/src/main/java/me/youhavetrouble/inviter/discord/command/ApiStatusChangeCommand.java +++ b/src/main/java/me/youhavetrouble/inviter/discord/command/ApiStatusChangeCommand.java @@ -19,14 +19,14 @@ public class ApiStatusChangeCommand extends Command { @Nullable public String getName() { - return "api"; + return "invites"; } public void register(JDA jda, String name) { - jda.upsertCommand(Commands.slash("api", "Change if Inviter API should allow to retrieve this server's invites.") + jda.upsertCommand(Commands.slash("invites", "Change or see if Inviter should create invites for this guild.") .setIntegrationTypes(IntegrationType.GUILD_INSTALL) .addOptions( - new OptionData(OptionType.BOOLEAN, "status", "Status of the api availability for this guild", false) + new OptionData(OptionType.BOOLEAN, "status", "Enable or disable Inviter to work for this guild", false) ) .setContexts(InteractionContextType.GUILD) .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) @@ -49,8 +49,8 @@ public class ApiStatusChangeCommand extends Command { GuildSettings setings = Main.getStorage().getGuildSettings(guild.getIdLong()); String message = setings.apiEnabled() ? - "Inviter API is currently __**enabled**__ for this server." : - "Inviter API is currently __**disabled**__ for this server."; + "Inviter is currently __**enabled**__ for this server." : + "Inviter is currently __**disabled**__ for this server."; event.getHook().editOriginal(message).queue(); return; @@ -59,8 +59,8 @@ public class ApiStatusChangeCommand extends Command { boolean status = statusMapping.getAsBoolean(); long guildId = guild.getIdLong(); - Main.getStorage().updateDiscordApiEnabled(guildId, status); - String message = status ? "Inviter API is now __**enabled**__ for this server." : "Inviter API is now __**disabled**__ for this server."; + Main.getStorage().updateInvitesEnabled(guildId, status); + String message = status ? "Inviter is now __**enabled**__ for this server." : "Inviter API is now __**disabled**__ for this server."; event.getHook().editOriginal(message).queue(); } diff --git a/src/main/java/me/youhavetrouble/inviter/discord/listener/GuildJoinAndLeaveListener.java b/src/main/java/me/youhavetrouble/inviter/discord/listener/GuildJoinAndLeaveListener.java index a2887a3..f883cff 100644 --- a/src/main/java/me/youhavetrouble/inviter/discord/listener/GuildJoinAndLeaveListener.java +++ b/src/main/java/me/youhavetrouble/inviter/discord/listener/GuildJoinAndLeaveListener.java @@ -19,9 +19,9 @@ public class GuildJoinAndLeaveListener extends ListenerAdapter { @Override public void onGuildLeave(@NotNull GuildLeaveEvent event) { - Storage storage = Main.getStorage(); long guildId = event.getGuild().getIdLong(); - storage.removeGuildSettings(guildId); + Main.getDiscordInviteMenager().removeFromCache(guildId); + Main.getStorage().removeGuildSettings(guildId); } } diff --git a/src/main/java/me/youhavetrouble/inviter/dns/DNSLookup.java b/src/main/java/me/youhavetrouble/inviter/dns/DNSLookup.java deleted file mode 100644 index d0839fc..0000000 --- a/src/main/java/me/youhavetrouble/inviter/dns/DNSLookup.java +++ /dev/null @@ -1,42 +0,0 @@ -package me.youhavetrouble.inviter.dns; - -import me.youhavetrouble.inviter.Main; -import org.jetbrains.annotations.NotNull; - -import javax.naming.directory.Attribute; -import javax.naming.directory.Attributes; -import javax.naming.directory.DirContext; -import javax.naming.directory.InitialDirContext; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Set; - -public class DNSLookup { - - public static Set getTxtRecords(@NotNull String hostname) throws Exception { - Hashtable env = new Hashtable<>(); - env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); - env.put("java.naming.provider.url", "dns://1.1.1.1"); - env.put("com.sun.jndi.dns.cache.ttl", "0"); - Set txtRecords = new HashSet<>(); - - DirContext ctx = new InitialDirContext(env); - Attributes attrs = ctx.getAttributes(hostname, new String[]{"TXT"}); - Attribute txtAttr = attrs.get("TXT"); - - if (txtAttr != null) { - for (int i = 0; i < txtAttr.size(); i++) { - Object record = txtAttr.get(i); - if (record instanceof String recordString) { - txtRecords.add(recordString); - } else if (record instanceof byte[]) { - txtRecords.add(new String((byte[]) record)); - } else { - txtRecords.add(record.toString()); - } - } - } - - return txtRecords; - } -} diff --git a/src/main/java/me/youhavetrouble/inviter/http/endpoints/GetDiscordInviteByGuildId.java b/src/main/java/me/youhavetrouble/inviter/http/endpoints/GetDiscordInviteByGuildId.java index 39db464..0c39e01 100644 --- a/src/main/java/me/youhavetrouble/inviter/http/endpoints/GetDiscordInviteByGuildId.java +++ b/src/main/java/me/youhavetrouble/inviter/http/endpoints/GetDiscordInviteByGuildId.java @@ -11,7 +11,7 @@ import java.util.regex.Pattern; public class GetDiscordInviteByGuildId implements EndpointHandler { - private final Pattern pathPattern = Pattern.compile("^/api/v1/discord/\\d{10,18}$"); + private final Pattern pathPattern = Pattern.compile("^/invite/\\d{10,18}$"); @NotNull @Override diff --git a/src/main/java/me/youhavetrouble/inviter/http/endpoints/MainEndpoint.java b/src/main/java/me/youhavetrouble/inviter/http/endpoints/MainEndpoint.java deleted file mode 100644 index aa7af60..0000000 --- a/src/main/java/me/youhavetrouble/inviter/http/endpoints/MainEndpoint.java +++ /dev/null @@ -1,49 +0,0 @@ -package me.youhavetrouble.inviter.http.endpoints; - -import com.sun.net.httpserver.HttpExchange; -import me.youhavetrouble.inviter.Main; -import me.youhavetrouble.inviter.discord.DiscordInvite; -import me.youhavetrouble.inviter.discord.DiscordInviteManager; -import me.youhavetrouble.inviter.discord.GuildSettings; -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.util.regex.Pattern; - -public class MainEndpoint implements EndpointHandler { - - private final Pattern pathPattern = Pattern.compile("^/$"); - - @NotNull - @Override - public Pattern pathPattern() { - return pathPattern; - } - - @Override - public void handle(@NotNull HttpExchange exchange) throws IOException { - if (!exchange.getRequestMethod().equals("GET")) { - exchange.sendResponseHeaders(405, -1); // Method Not Allowed - return; - } - - String host = exchange.getRemoteAddress().getHostName(); - - GuildSettings guildSettings = Main.getStorage().getGuildSettings(host); - if (guildSettings == null) { - exchange.sendResponseHeaders(404, -1); // Not Found - return; - } - - DiscordInviteManager inviteManager = Main.getDiscordInviteMenager(); - DiscordInvite invite = inviteManager.getInvite(guildSettings.guildId()); - - if (invite == null) { - exchange.sendResponseHeaders(404, -1); // Not Found - return; - } - - exchange.getResponseHeaders().set("Location", "https://discord.gg/" + invite.code()); - exchange.sendResponseHeaders(307, -1); - } -} diff --git a/src/main/java/me/youhavetrouble/inviter/storage/SqliteStorage.java b/src/main/java/me/youhavetrouble/inviter/storage/SqliteStorage.java index 91f62fb..37d44b3 100644 --- a/src/main/java/me/youhavetrouble/inviter/storage/SqliteStorage.java +++ b/src/main/java/me/youhavetrouble/inviter/storage/SqliteStorage.java @@ -4,7 +4,6 @@ import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import me.youhavetrouble.inviter.discord.GuildSettings; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.sql.DataSource; import java.io.File; @@ -12,7 +11,6 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.List; public class SqliteStorage implements Storage { @@ -39,18 +37,10 @@ public class SqliteStorage implements Storage { connection.createStatement().execute(""" CREATE TABLE IF NOT EXISTS guild_settings ( guild_id LONG PRIMARY KEY, - api_enabled BOOLEAN NOT NULL DEFAULT FALSE + invites_enabled BOOLEAN NOT NULL DEFAULT FALSE ); """ ); - connection.createStatement().execute(""" - CREATE TABLE IF NOT EXISTS hostnames ( - hostname VARCHAR(256) PRIMARY KEY, - guild_id LONG NOT NULL, - failed_checks INTEGER NOT NULL DEFAULT 0, - FOREIGN KEY (guild_id) REFERENCES guild_settings(guild_id) ON DELETE CASCADE - ) - """); } catch (SQLException e) { throw new RuntimeException("Failed to initialize database", e); } @@ -69,39 +59,16 @@ public class SqliteStorage implements Storage { ResultSet resultSet = statement.executeQuery(); if (resultSet.next()) { - boolean apiEnabled = resultSet.getBoolean("api_enabled"); - String apiHostname = resultSet.getString("hostname"); - return new GuildSettings(guildId, apiEnabled, apiHostname); + boolean invitesEnabled = resultSet.getBoolean("invites_enabled"); + return new GuildSettings(guildId, invitesEnabled); } - return new GuildSettings(guildId,false, null); + return new GuildSettings(guildId,false); } catch (SQLException e) { throw new RuntimeException("Failed to retrieve guild settings", e); } } - @Nullable - @Override - public GuildSettings getGuildSettings(@NotNull String hostname) { - - try (Connection connection = dataSource.getConnection()) { - PreparedStatement statement = connection.prepareStatement( - "SELECT * FROM guild_settings WHERE hostname = ?" - ); - statement.setString(1, hostname); - ResultSet resultSet = statement.executeQuery(); - - if (resultSet.next()) { - long guildId = resultSet.getLong("guild_id"); - boolean apiEnabled = resultSet.getBoolean("api_enabled"); - return new GuildSettings(guildId, apiEnabled, hostname); - } - return null; // No settings found for the given hostname - } catch (SQLException e) { - throw new RuntimeException("Failed to retrieve guild settings by hostname", e); - } - } - @Override public void saveDefaultGuildSettings(long guildId) { try (Connection connection = dataSource.getConnection()) { @@ -129,10 +96,10 @@ public class SqliteStorage implements Storage { } @Override - public void updateDiscordApiEnabled(long guildId, boolean enabled) { + public void updateInvitesEnabled(long guildId, boolean enabled) { try (Connection connection = dataSource.getConnection()) { PreparedStatement statement = connection.prepareStatement( - "UPDATE guild_settings SET api_enabled = ? WHERE guild_id = ?" + "UPDATE guild_settings SET invites_enabled = ? WHERE guild_id = ?" ); statement.setBoolean(1, enabled); statement.setLong(2, guildId); @@ -143,63 +110,4 @@ public class SqliteStorage implements Storage { } - @Override - public void addHostname(long guildId, @Nullable String hostname) { - try (Connection connection = dataSource.getConnection()) { - PreparedStatement statement = connection.prepareStatement( - "INSERT OR IGNORE INTO hostnames (hostname, guild_id) VALUES (?, ?)" - ); - statement.setString(1, hostname); - statement.setLong(2, guildId); - statement.executeUpdate(); - } catch (SQLException e) { - throw new RuntimeException("Failed to add hostname", e); - } - } - - @Override - public void removeHostname(@NotNull String hostname) { - try (Connection connection = dataSource.getConnection()) { - PreparedStatement statement = connection.prepareStatement( - "DELETE FROM hostnames WHERE hostname = ?" - ); - statement.setString(1, hostname); - statement.executeUpdate(); - } catch (SQLException e) { - throw new RuntimeException("Failed to remove hostname", e); - } - - } - - @Override - public List listHostnames(long guildId) { - try (Connection connection = dataSource.getConnection()) { - PreparedStatement statement = connection.prepareStatement( - "SELECT hostname FROM hostnames WHERE guild_id = ?" - ); - statement.setLong(1, guildId); - ResultSet resultSet = statement.executeQuery(); - - List hostnames = new java.util.ArrayList<>(); - while (resultSet.next()) { - hostnames.add(resultSet.getString("hostname")); - } - return hostnames; - } catch (SQLException e) { - throw new RuntimeException("Failed to list hostnames", e); - } - } - - @Override - public void cleanUpHostnames() { - try (Connection connection = dataSource.getConnection()) { - PreparedStatement statement = connection.prepareStatement( - "DELETE FROM hostnames WHERE failed_checks >= 3" - ); - statement.executeUpdate(); - } catch (SQLException e) { - throw new RuntimeException("Failed to clean up hostnames", e); - } - } - } diff --git a/src/main/java/me/youhavetrouble/inviter/storage/Storage.java b/src/main/java/me/youhavetrouble/inviter/storage/Storage.java index e4d21ad..bc53436 100644 --- a/src/main/java/me/youhavetrouble/inviter/storage/Storage.java +++ b/src/main/java/me/youhavetrouble/inviter/storage/Storage.java @@ -3,28 +3,15 @@ package me.youhavetrouble.inviter.storage; import me.youhavetrouble.inviter.discord.GuildSettings; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; public interface Storage { @NotNull GuildSettings getGuildSettings(long guildId); - @Nullable GuildSettings getGuildSettings(@NotNull String hostname); - void saveDefaultGuildSettings(long guildId); void removeGuildSettings(long guildId); - void updateDiscordApiEnabled(long guildId, boolean enabled); - - void addHostname(long guildId, @Nullable String hostname); - - void removeHostname(@NotNull String hostname); - - List listHostnames(long guildId); - - void cleanUpHostnames(); + void updateInvitesEnabled(long guildId, boolean enabled); }