initial bot and in-memory storage
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
package me.youhavetrouble.inviter;
|
||||
|
||||
public record DiscordInvite(
|
||||
String code,
|
||||
Long guildId,
|
||||
Long expiresAt
|
||||
) {
|
||||
|
||||
public DiscordInvite {
|
||||
if (code == null) {
|
||||
throw new IllegalArgumentException("Code cannot be null");
|
||||
}
|
||||
if (guildId == null || guildId <= 0) {
|
||||
throw new IllegalArgumentException("Guild ID must not be null nor be a negative number");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package me.youhavetrouble.inviter;
|
||||
|
||||
import me.youhavetrouble.inviter.storage.MemoryStorage;
|
||||
import me.youhavetrouble.inviter.storage.Storage;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.JDABuilder;
|
||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||
import net.dv8tion.jda.api.utils.cache.CacheFlag;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class Main {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Inviter");
|
||||
|
||||
private static JDA jda;
|
||||
|
||||
private static Storage storage;
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
|
||||
String token = System.getenv("DISCORD_TOKEN");
|
||||
|
||||
jda = JDABuilder.create(
|
||||
token,
|
||||
Set.of(GatewayIntent.GUILD_INVITES)
|
||||
)
|
||||
.disableCache(
|
||||
CacheFlag.ACTIVITY,
|
||||
CacheFlag.VOICE_STATE,
|
||||
CacheFlag.EMOJI,
|
||||
CacheFlag.STICKER,
|
||||
CacheFlag.CLIENT_STATUS,
|
||||
CacheFlag.ONLINE_STATUS,
|
||||
CacheFlag.SCHEDULED_EVENTS
|
||||
)
|
||||
.build();
|
||||
|
||||
jda.awaitReady();
|
||||
|
||||
storage = new MemoryStorage(jda);
|
||||
|
||||
LOGGER.info("Welcome to the Inviter Application!");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package me.youhavetrouble.inviter.storage;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import me.youhavetrouble.inviter.DiscordInvite;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Invite;
|
||||
import net.dv8tion.jda.api.entities.channel.unions.DefaultGuildChannelUnion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
public class MemoryStorage implements Storage {
|
||||
|
||||
private final Cache<String, DiscordInvite> cache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(Duration.of(60, ChronoUnit.SECONDS))
|
||||
.build();
|
||||
|
||||
private final JDA jda;
|
||||
|
||||
public MemoryStorage(JDA jda) {
|
||||
this.jda = jda;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DiscordInvite getInvite(long guildId) {
|
||||
DiscordInvite discordInvite = cache.getIfPresent(String.valueOf(guildId));
|
||||
if (discordInvite == null || discordInvite.isExpired()) {
|
||||
Guild guild = jda.getGuildById(guildId);
|
||||
if (guild == null) {
|
||||
return null; // Guild not found
|
||||
}
|
||||
DefaultGuildChannelUnion defaultChannel = guild.getDefaultChannel();
|
||||
if (defaultChannel == null) {
|
||||
return null; // No default channel found
|
||||
}
|
||||
Invite invite = defaultChannel.createInvite()
|
||||
.setMaxAge(60) // Set the invite to expire after 60 seconds
|
||||
.complete();
|
||||
if (invite == null) return null; // Failed to create invite
|
||||
discordInvite = new DiscordInvite(
|
||||
invite.getCode(),
|
||||
guild.getIdLong(),
|
||||
invite.getTimeCreated().toEpochSecond()
|
||||
);
|
||||
}
|
||||
return discordInvite;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DiscordInvite saveInvite(Invite invite) {
|
||||
|
||||
if (invite == null) {
|
||||
throw new IllegalArgumentException("Invite cannot be null");
|
||||
}
|
||||
if (invite.getGuild() == null) {
|
||||
throw new IllegalArgumentException("Invite must be associated with a guild");
|
||||
}
|
||||
|
||||
DiscordInvite discordInvite = new DiscordInvite(
|
||||
invite.getCode(),
|
||||
invite.getGuild().getIdLong(),
|
||||
invite.getTimeCreated().toEpochSecond()
|
||||
);
|
||||
|
||||
cache.put(invite.getGuild().getId(), discordInvite);
|
||||
return discordInvite;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package me.youhavetrouble.inviter.storage;
|
||||
|
||||
import me.youhavetrouble.inviter.DiscordInvite;
|
||||
import net.dv8tion.jda.api.entities.Invite;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface Storage {
|
||||
|
||||
@Nullable DiscordInvite getInvite(long guildId);
|
||||
|
||||
/**
|
||||
* Saves the invite to the storage and returns the saved invite.
|
||||
* @param invite JDA invite object to save
|
||||
* @return the saved DiscordInvite object
|
||||
*/
|
||||
@NotNull DiscordInvite saveInvite(Invite invite);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<Configuration name="Console">
|
||||
|
||||
<Properties>
|
||||
<Property name="LOG_PATTERN">[%d{yyyy-MM-dd HH:mm:ss}] [%t/%p]: %msg%n</Property>
|
||||
</Properties>
|
||||
|
||||
<Appenders>
|
||||
|
||||
<Console name="ConsoleTerminal" target="SYSTEM_OUT" follow="true">
|
||||
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%p]: %msg%n"/>
|
||||
</Console>
|
||||
|
||||
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz" immediateFlush="false">
|
||||
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%t/%p]: %msg%n"/>
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy/>
|
||||
<OnStartupTriggeringPolicy/>
|
||||
</Policies>
|
||||
</RollingRandomAccessFile>
|
||||
</Appenders>
|
||||
|
||||
<Loggers>
|
||||
<Root level="INFO">
|
||||
<AppenderRef ref="ConsoleTerminal"/>
|
||||
<AppenderRef ref="File"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
Reference in New Issue
Block a user