✨ Ajout du système d'avertissement
This commit is contained in:
parent
2f020dc5a7
commit
1cce7f01b7
@ -2,3 +2,7 @@ BOT_TOKEN=
|
|||||||
GUILD_ID=
|
GUILD_ID=
|
||||||
DEFAULT_ROLE_ID=
|
DEFAULT_ROLE_ID=
|
||||||
ROLE_ID=
|
ROLE_ID=
|
||||||
|
LOG_CHANNEL_ID=
|
||||||
|
DB_URL=jdbc:postgresql://localhost:5434/kiss_shot_acerola
|
||||||
|
DB_USER=postgres
|
||||||
|
DB_PASSWORD=kiss_shot_acerola
|
@ -17,10 +17,14 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation("org.hibernate:hibernate-core:6.6.2.Final")
|
||||||
|
implementation("org.hibernate:hibernate-hikaricp:6.6.2.Final")
|
||||||
|
implementation("org.postgresql:postgresql:42.7.4")
|
||||||
implementation("io.github.cdimascio:dotenv-kotlin:6.4.2")
|
implementation("io.github.cdimascio:dotenv-kotlin:6.4.2")
|
||||||
implementation("net.dv8tion:JDA:5.2.1")
|
implementation("net.dv8tion:JDA:5.2.1")
|
||||||
implementation("ch.qos.logback:logback-classic:1.5.12")
|
implementation("ch.qos.logback:logback-classic:1.5.12")
|
||||||
implementation ("dev.arbjerg:lavaplayer:2.2.2")
|
implementation ("dev.arbjerg:lavaplayer:2.2.2")
|
||||||
|
implementation("jakarta.annotation:jakarta.annotation-api:3.0.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
13
docker-compose.yml
Normal file
13
docker-compose.yml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:17
|
||||||
|
environment:
|
||||||
|
POSTGRES_PASSWORD: kiss_shot_acerola
|
||||||
|
POSTGRES_DB: kiss_shot_acerola
|
||||||
|
ports:
|
||||||
|
- "5434:5432"
|
||||||
|
volumes:
|
||||||
|
- postgres_kiss_shot_acerola_data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_kiss_shot_acerola_data:
|
@ -1,11 +1,14 @@
|
|||||||
package org.camelia.studio.kiss.shot.acerola;
|
package org.camelia.studio.kiss.shot.acerola;
|
||||||
|
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.db.HibernateConfig;
|
||||||
import org.camelia.studio.kiss.shot.acerola.listeners.bot.ReadyListener;
|
import org.camelia.studio.kiss.shot.acerola.listeners.bot.ReadyListener;
|
||||||
import org.camelia.studio.kiss.shot.acerola.managers.ListenerManager;
|
import org.camelia.studio.kiss.shot.acerola.managers.ListenerManager;
|
||||||
import org.camelia.studio.kiss.shot.acerola.utils.Configuration;
|
import org.camelia.studio.kiss.shot.acerola.utils.Configuration;
|
||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
import net.dv8tion.jda.api.JDABuilder;
|
import net.dv8tion.jda.api.JDABuilder;
|
||||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||||
|
import net.dv8tion.jda.api.utils.MemberCachePolicy;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -20,13 +23,14 @@ public class KissShotAcerola {
|
|||||||
jda = JDABuilder.createDefault(Configuration.getInstance().getDotenv().get("BOT_TOKEN"))
|
jda = JDABuilder.createDefault(Configuration.getInstance().getDotenv().get("BOT_TOKEN"))
|
||||||
.addEventListeners(new ReadyListener())
|
.addEventListeners(new ReadyListener())
|
||||||
.enableIntents(GatewayIntent.getIntents(GatewayIntent.ALL_INTENTS))
|
.enableIntents(GatewayIntent.getIntents(GatewayIntent.ALL_INTENTS))
|
||||||
|
.setMemberCachePolicy(MemberCachePolicy.ALL)
|
||||||
.build()
|
.build()
|
||||||
.awaitReady()
|
.awaitReady();
|
||||||
;
|
|
||||||
|
|
||||||
new ListenerManager().registerListeners(jda);
|
new ListenerManager().registerListeners(jda);
|
||||||
|
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||||
|
HibernateConfig.shutdown();
|
||||||
jda.shutdown();
|
jda.shutdown();
|
||||||
}));
|
}));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -0,0 +1,126 @@
|
|||||||
|
package org.camelia.studio.kiss.shot.acerola.commands.moderation;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.interfaces.ISlashCommand;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.models.Averto;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.models.User;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.repositories.AvertoRepository;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.services.UserService;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.utils.Configuration;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder;
|
||||||
|
import net.dv8tion.jda.api.Permission;
|
||||||
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import net.dv8tion.jda.api.entities.Message.Attachment;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||||
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||||
|
import net.dv8tion.jda.api.utils.FileUpload;
|
||||||
|
|
||||||
|
public class AvertoCommand implements ISlashCommand {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "averto";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Permet d'avertir un utilisateur";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<OptionData> getOptions() {
|
||||||
|
return List.of(
|
||||||
|
new OptionData(OptionType.USER, "utilisateur", "L'utilisateur à avertir", true),
|
||||||
|
new OptionData(OptionType.STRING, "raison", "La raison de l'avertissement", false),
|
||||||
|
new OptionData(OptionType.ATTACHMENT, "file", "Une preuve de l'avertissement", false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefaultMemberPermissions defaultPermissions() {
|
||||||
|
return DefaultMemberPermissions.enabledFor(Permission.MESSAGE_MANAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(SlashCommandInteractionEvent event) {
|
||||||
|
event.deferReply().setEphemeral(true).queue();
|
||||||
|
try {
|
||||||
|
Member moderator = event.getMember();
|
||||||
|
Member member = event.getOption("utilisateur").getAsMember();
|
||||||
|
|
||||||
|
OptionMapping raisonOptionMapping = event.getOption("raison");
|
||||||
|
String reason = raisonOptionMapping == null ? "Aucune raison spécifiée" : raisonOptionMapping.getAsString();
|
||||||
|
|
||||||
|
OptionMapping fileOptionMapping = event.getOption("file");
|
||||||
|
Attachment file = null;
|
||||||
|
String fileUrl = null;
|
||||||
|
TextChannel logChannel = event.getGuild()
|
||||||
|
.getTextChannelById(Configuration.getInstance().getDotenv().get("LOG_CHANNEL_ID"));
|
||||||
|
|
||||||
|
if (fileOptionMapping != null) {
|
||||||
|
file = fileOptionMapping.getAsAttachment();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logChannel != null) {
|
||||||
|
File fileTemp = null;
|
||||||
|
if (file != null) {
|
||||||
|
fileTemp = File.createTempFile("proof_" + member.getId() + "_", "." + file.getFileExtension());
|
||||||
|
fileTemp = file.getProxy().downloadToFile(fileTemp).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Message message = this.sendLogMessage(logChannel, member, fileTemp, reason);
|
||||||
|
|
||||||
|
if (fileTemp != null) {
|
||||||
|
fileUrl = message.getAttachments().get(0).getUrl();
|
||||||
|
fileTemp.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
User memberUser = UserService.getInstance().getOrCreateUser(member.getId());
|
||||||
|
User moderatorUser = UserService.getInstance().getOrCreateUser(moderator.getId());
|
||||||
|
|
||||||
|
Averto averto = new Averto(memberUser, moderatorUser);
|
||||||
|
averto.setReason(reason);
|
||||||
|
averto.setFile(fileUrl);
|
||||||
|
|
||||||
|
AvertoRepository.getInstance().save(averto);
|
||||||
|
|
||||||
|
// On tente d'envoyer un message privé à l'utilisateur averti
|
||||||
|
member.getUser().openPrivateChannel().queue(privateChannel -> {
|
||||||
|
privateChannel
|
||||||
|
.sendMessage("Bonjour, Vous avez été averti sur %s pour la raison suivante : %s".formatted(
|
||||||
|
event.getGuild().getName(), reason != null ? reason : "Aucune raison spécifiée"))
|
||||||
|
.queue();
|
||||||
|
});
|
||||||
|
|
||||||
|
event.getHook().editOriginal("L'utilisateur %s a bien été averti !".formatted(member.getAsMention()))
|
||||||
|
.queue();
|
||||||
|
} catch (Exception e) {
|
||||||
|
event.getHook().editOriginal("Une erreur est survenue lors de l'avertissement, " + e.getMessage()).queue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Message sendLogMessage(TextChannel logChannel, Member member, File fileTemp, String reason) {
|
||||||
|
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||||
|
embedBuilder.setTitle("Avertissement - Règlement enfreint");
|
||||||
|
embedBuilder.setDescription("Un utilisateur a été averti pour non respect du règlement");
|
||||||
|
embedBuilder.addField("Utilisateur", member.getAsMention(), false);
|
||||||
|
embedBuilder.addField("Raison", reason != null ? reason : "Aucune raison spécifié", false);
|
||||||
|
|
||||||
|
Message msg = logChannel.sendMessageEmbeds(embedBuilder.build()).complete();
|
||||||
|
|
||||||
|
if (fileTemp != null) {
|
||||||
|
msg = logChannel
|
||||||
|
.sendFiles(FileUpload.fromData(fileTemp)).complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
package org.camelia.studio.kiss.shot.acerola.commands.moderation;
|
||||||
|
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.interfaces.ISlashCommand;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.models.Averto;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.models.User;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.services.AvertoService;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.services.UserService;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder;
|
||||||
|
import net.dv8tion.jda.api.Permission;
|
||||||
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||||
|
|
||||||
|
public class AvertoListCommand implements ISlashCommand {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "avertolist";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Liste les avertissements d'un utilisateur";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefaultMemberPermissions defaultPermissions() {
|
||||||
|
return DefaultMemberPermissions.enabledFor(Permission.MESSAGE_MANAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<OptionData> getOptions() {
|
||||||
|
return List.of(
|
||||||
|
new OptionData(
|
||||||
|
OptionType.USER,
|
||||||
|
"utilisateur",
|
||||||
|
"L'utilisateur dont vous voulez voir les avertissements",
|
||||||
|
false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(SlashCommandInteractionEvent event) {
|
||||||
|
event.deferReply().setEphemeral(true).queue();
|
||||||
|
OptionMapping option = event.getOption("utilisateur");
|
||||||
|
|
||||||
|
Member member = null;
|
||||||
|
List<Averto> avertos = null;
|
||||||
|
User user = null;
|
||||||
|
|
||||||
|
if (option != null) {
|
||||||
|
member = option.getAsMember();
|
||||||
|
user = UserService.getInstance().getOrCreateUser(member.getId());
|
||||||
|
avertos = user.getAvertos();
|
||||||
|
} else {
|
||||||
|
avertos = AvertoService.getInstance().getLatestAvertos(10);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 2 possibilités :
|
||||||
|
* - Aucun utilisateur : On affiche les 10 derniers avertissements du serveur
|
||||||
|
* - Un utilisateur : On affiche les avertissements de cet utilisateur
|
||||||
|
*/
|
||||||
|
|
||||||
|
EmbedBuilder embedBuilder = new EmbedBuilder()
|
||||||
|
.setTitle("Avertissements de " + (member == null ? "tous les utilisateurs" : member.getEffectiveName()))
|
||||||
|
.setColor(0xFF0000);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (Averto averto : avertos) {
|
||||||
|
count++;
|
||||||
|
if (count > 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// On récupère le membre Discord de l'utilisateur
|
||||||
|
Member discordUser = event.getGuild().getMemberById(averto.getUser().getDiscordId());
|
||||||
|
Member moderator = event.getGuild().getMemberById(averto.getModerator().getDiscordId());
|
||||||
|
embedBuilder.addField(
|
||||||
|
"Avertissement #" + averto.getId(),
|
||||||
|
(discordUser != null ? "Utilisateur : " + discordUser.getAsMention() + "\n" : "") +
|
||||||
|
"Raison : " + averto.getReason() + "\n" +
|
||||||
|
(moderator != null ? "Modérateur : " + moderator.getAsMention() : "") + "\n" +
|
||||||
|
"Date : "
|
||||||
|
+ averto.getCreatedAt().format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm")) +
|
||||||
|
"\n" +
|
||||||
|
"Preuve : " + (averto.getFile() != null ? averto.getFile() : "Aucune"),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
event.getHook().editOriginalEmbeds(embedBuilder.build()).queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package org.camelia.studio.kiss.shot.acerola.db;
|
||||||
|
|
||||||
|
import io.github.cdimascio.dotenv.Dotenv;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.interfaces.IEntity;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.utils.ReflectionUtils;
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
public class HibernateConfig {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(HibernateConfig.class);
|
||||||
|
private static SessionFactory sessionFactory;
|
||||||
|
|
||||||
|
public static SessionFactory getSessionFactory() {
|
||||||
|
if (sessionFactory == null) {
|
||||||
|
try {
|
||||||
|
logger.info("Initializing Hibernate SessionFactory");
|
||||||
|
Dotenv dotenv = org.camelia.studio.kiss.shot.acerola.utils.Configuration.getInstance().getDotenv();
|
||||||
|
|
||||||
|
Properties props = new Properties();
|
||||||
|
|
||||||
|
// Configuration Hibernate
|
||||||
|
props.put(Environment.HBM2DDL_AUTO, "update"); // On utilise validate au lieu de update
|
||||||
|
|
||||||
|
props.put(Environment.GLOBALLY_QUOTED_IDENTIFIERS, "true");
|
||||||
|
|
||||||
|
// Configuration HikariCP
|
||||||
|
props.put("hibernate.connection.provider_class",
|
||||||
|
"org.hibernate.hikaricp.internal.HikariCPConnectionProvider");
|
||||||
|
props.put("hibernate.hikari.minimumIdle", "5");
|
||||||
|
props.put("hibernate.hikari.maximumPoolSize", "10");
|
||||||
|
props.put("hibernate.hikari.idleTimeout", "300000");
|
||||||
|
props.put("hibernate.hikari.dataSourceClassName",
|
||||||
|
"org.postgresql.ds.PGSimpleDataSource");
|
||||||
|
props.put("hibernate.hikari.dataSource.url", dotenv.get("DB_URL"));
|
||||||
|
props.put("hibernate.hikari.dataSource.user", dotenv.get("DB_USER"));
|
||||||
|
props.put("hibernate.hikari.dataSource.password", dotenv.get("DB_PASSWORD"));
|
||||||
|
|
||||||
|
Configuration configuration = new Configuration();
|
||||||
|
configuration.setProperties(props);
|
||||||
|
|
||||||
|
List<IEntity> entities = ReflectionUtils.loadClasses(
|
||||||
|
"org.camelia.studio.kiss.shot.acerola.models",
|
||||||
|
IEntity.class);
|
||||||
|
|
||||||
|
for (IEntity entity : entities) {
|
||||||
|
configuration.addAnnotatedClass(entity.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
|
||||||
|
.applySettings(configuration.getProperties())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
|
||||||
|
logger.info("Hibernate SessionFactory initialized successfully");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Failed to initialize Hibernate SessionFactory", e);
|
||||||
|
throw new RuntimeException("Failed to initialize Hibernate SessionFactory", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sessionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void shutdown() {
|
||||||
|
logger.info("Shutting down database connections");
|
||||||
|
if (sessionFactory != null && !sessionFactory.isClosed()) {
|
||||||
|
try {
|
||||||
|
sessionFactory.close();
|
||||||
|
logger.info("SessionFactory closed successfully");
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error closing SessionFactory", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package org.camelia.studio.kiss.shot.acerola.interfaces;
|
||||||
|
|
||||||
|
public interface IEntity {
|
||||||
|
}
|
@ -1,16 +1,23 @@
|
|||||||
package org.camelia.studio.kiss.shot.acerola.interfaces;
|
package org.camelia.studio.kiss.shot.acerola.interfaces;
|
||||||
|
|
||||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface ISlashCommand {
|
public interface ISlashCommand {
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
String getDescription();
|
String getDescription();
|
||||||
|
|
||||||
void execute(SlashCommandInteractionEvent event);
|
void execute(SlashCommandInteractionEvent event);
|
||||||
|
|
||||||
default List<OptionData> getOptions() {
|
default List<OptionData> getOptions() {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
default DefaultMemberPermissions defaultPermissions() {
|
||||||
|
return DefaultMemberPermissions.ENABLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
package org.camelia.studio.kiss.shot.acerola.models;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.interfaces.IEntity;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
|
import org.hibernate.annotations.UpdateTimestamp;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "avertos")
|
||||||
|
public class Averto implements IEntity {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.EAGER)
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.EAGER)
|
||||||
|
private User moderator;
|
||||||
|
|
||||||
|
@Column(name = "reason", nullable = true, unique = false)
|
||||||
|
private String reason;
|
||||||
|
|
||||||
|
@Column(name = "file", nullable = true, unique = false)
|
||||||
|
private String file;
|
||||||
|
|
||||||
|
@CreationTimestamp
|
||||||
|
@Column(name = "createdAt")
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
@UpdateTimestamp
|
||||||
|
@Column(name = "updatedAt")
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public Averto() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Averto(User user, User moderator) {
|
||||||
|
this.user = user;
|
||||||
|
this.moderator = moderator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReason() {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFile(String file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReason(String reason) {
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getModerator() {
|
||||||
|
return moderator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
package org.camelia.studio.kiss.shot.acerola.models;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.interfaces.IEntity;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
|
import org.hibernate.annotations.UpdateTimestamp;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "users")
|
||||||
|
public class User implements IEntity {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
|
||||||
|
private List<Averto> avertos;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "moderator", fetch = FetchType.EAGER)
|
||||||
|
private List<Averto> moderatedAvertos;
|
||||||
|
|
||||||
|
@Column(name = "discordId", nullable = false, unique = true)
|
||||||
|
private String discordId;
|
||||||
|
|
||||||
|
@CreationTimestamp
|
||||||
|
@Column(name = "createdAt")
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
@UpdateTimestamp
|
||||||
|
@Column(name = "updatedAt")
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(String discordId) {
|
||||||
|
this.discordId = discordId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDiscordId() {
|
||||||
|
return discordId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDiscordId(String discordId) {
|
||||||
|
this.discordId = discordId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Averto> getAvertos() {
|
||||||
|
return avertos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Averto> getModeratedAvertos() {
|
||||||
|
return moderatedAvertos;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package org.camelia.studio.kiss.shot.acerola.repositories;
|
||||||
|
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.db.HibernateConfig;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.models.Averto;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.hibernate.query.Order;
|
||||||
|
import org.hibernate.query.SortDirection;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AvertoRepository {
|
||||||
|
private final SessionFactory sessionFactory;
|
||||||
|
private static AvertoRepository instance;
|
||||||
|
|
||||||
|
public static AvertoRepository getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new AvertoRepository();
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AvertoRepository() {
|
||||||
|
this.sessionFactory = HibernateConfig.getSessionFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Averto> findAll() {
|
||||||
|
try (Session session = sessionFactory.openSession()) {
|
||||||
|
return session.createQuery("FROM User", Averto.class)
|
||||||
|
.setOrder(Order.by(Averto.class, "createdAt", SortDirection.DESCENDING))
|
||||||
|
.list();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Averto> findCount(int count) {
|
||||||
|
try (Session session = sessionFactory.openSession()) {
|
||||||
|
return session.createQuery("FROM Averto", Averto.class)
|
||||||
|
.setOrder(Order.by(Averto.class, "createdAt", SortDirection.DESCENDING))
|
||||||
|
.setMaxResults(count)
|
||||||
|
.list();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Averto save(Averto averto) {
|
||||||
|
try (Session session = sessionFactory.openSession()) {
|
||||||
|
session.beginTransaction();
|
||||||
|
session.persist(averto);
|
||||||
|
session.getTransaction().commit();
|
||||||
|
return averto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package org.camelia.studio.kiss.shot.acerola.repositories;
|
||||||
|
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.db.HibernateConfig;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.models.User;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class UserRepository {
|
||||||
|
private final SessionFactory sessionFactory;
|
||||||
|
private static UserRepository instance;
|
||||||
|
|
||||||
|
public static UserRepository getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new UserRepository();
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRepository() {
|
||||||
|
this.sessionFactory = HibernateConfig.getSessionFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<User> findAll() {
|
||||||
|
try (Session session = sessionFactory.openSession()) {
|
||||||
|
return session.createQuery("FROM User", User.class).list();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public User findByDiscordId(String discordId) {
|
||||||
|
try (Session session = sessionFactory.openSession()) {
|
||||||
|
return session.createQuery("FROM User WHERE discordId = :discordId", User.class)
|
||||||
|
.setParameter("discordId", discordId)
|
||||||
|
.uniqueResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public User save(User user) {
|
||||||
|
try (Session session = sessionFactory.openSession()) {
|
||||||
|
session.beginTransaction();
|
||||||
|
session.persist(user);
|
||||||
|
session.getTransaction().commit();
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(User user) {
|
||||||
|
try (Session session = sessionFactory.openSession()) {
|
||||||
|
session.beginTransaction();
|
||||||
|
session.merge(user);
|
||||||
|
session.getTransaction().commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.camelia.studio.kiss.shot.acerola.services;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.models.Averto;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.repositories.AvertoRepository;
|
||||||
|
|
||||||
|
public class AvertoService {
|
||||||
|
private static AvertoService instance;
|
||||||
|
|
||||||
|
public static AvertoService getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new AvertoService();
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Averto> getLatestAvertos(int amount) {
|
||||||
|
return AvertoRepository.getInstance().findCount(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package org.camelia.studio.kiss.shot.acerola.services;
|
||||||
|
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.models.*;
|
||||||
|
import org.camelia.studio.kiss.shot.acerola.repositories.UserRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class UserService {
|
||||||
|
private static UserService instance;
|
||||||
|
|
||||||
|
public static UserService getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new UserService();
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getOrCreateUser(String discordId) {
|
||||||
|
User user = UserRepository.getInstance().findByDiscordId(discordId);
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
user = new User(discordId);
|
||||||
|
UserRepository.getInstance().save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<User> getAllUsers() {
|
||||||
|
return UserRepository.getInstance().findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateUser(User user) {
|
||||||
|
UserRepository.getInstance().update(user);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user