From df3227a10dfc0186f634f9b92398765626fd2e91 Mon Sep 17 00:00:00 2001 From: PhysX Date: Fri, 7 Aug 2026 01:12:38 +0200 Subject: [PATCH 1/6] Add Dockerfile and update Jenkinsfile for Docker integration for preproduction and production --- Dockerfile | 4 +++ Jenkinsfile | 86 +++++++++++++++++++---------------------------------- 2 files changed, 34 insertions(+), 56 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f2d311f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM eclipse-temurin:21-jre +WORKDIR /app +COPY build/libs/ClicBot-1.0-SNAPSHOT.jar app.jar +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 4837f55..8310015 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,75 +1,49 @@ pipeline { agent any - tools { - jdk 'jdk-21' - } - stages { - stage('Checkout') { + stage('Build') { steps { - git branch: 'master', - url: 'https://github.com/physx322/ClicBot.git', - credentialsId: 'gh' + sh './gradlew build' } } - stage('Build') { + stage('Build image') { steps { - sh 'chmod +x gradlew' - sh './gradlew clean build -x test' + sh 'docker build -t ares-bot:${BRANCH_NAME} .' } } - stage('Archive') { + stage('Deploy Preprod') { + when { branch 'develop' } + environment { + DISCORD_TOKEN = credentials('discord-token-preprod') + } steps { - archiveArtifacts artifacts: 'build/libs/*.jar', fingerprint: true + sh ''' + docker stop bot-preprod || true + docker rm bot-preprod || true + docker run -d --name bot-preprod \ + -e BOT_TOKEN=$DISCORD_TOKEN \ + ares-bot:develop + ''' } } - } -post { - success { - withCredentials([string(credentialsId: 'discord-webhook', variable: 'DISCORD_URL')]) { - script { - def duration = currentBuild.durationString.replace(' and counting', '') - discordSend( - webhookURL: "${DISCORD_URL}", - title: "✅ Build réussi — ${env.JOB_NAME} #${env.BUILD_NUMBER}", - description: """ - **Projet:** ${env.JOB_NAME} - **Branche:** ${env.GIT_BRANCH} - **Commit:** ${env.GIT_COMMIT?.take(7)} - **Auteur:** ${env.GIT_AUTHOR_NAME ?: 'N/A'} - **Durée:** ${duration} - """, - link: env.BUILD_URL, - successful: true, - footer: "Jenkins Pipeline" - ) + + stage('Deploy Prod') { + when { branch 'master' } + environment { + DISCORD_TOKEN = credentials('discord-token-prod') } - } - } - failure { - withCredentials([string(credentialsId: 'discord-webhook', variable: 'DISCORD_URL')]) { - script { - def duration = currentBuild.durationString.replace(' and counting', '') - discordSend( - webhookURL: "${DISCORD_URL}", - title: "❌ Build échoué — ${env.JOB_NAME} #${env.BUILD_NUMBER}", - description: """ - **Projet:** ${env.JOB_NAME} - **Branche:** ${env.GIT_BRANCH} - **Commit:** ${env.GIT_COMMIT?.take(7)} - **Auteur:** ${env.GIT_AUTHOR_NAME ?: 'N/A'} - **Durée:** ${duration} - **Étape échouée:** ${env.STAGE_NAME ?: 'Inconnue'} - """, - link: env.BUILD_URL, - result: currentBuild.currentResult, - footer: "Jenkins Pipeline" - ) + steps { + sh ''' + docker stop bot-prod || true + docker rm bot-prod || true + docker run -d --name bot-prod \ + -e BOT_TOKEN=$DISCORD_TOKEN \ + ares-bot:master + ''' } } } -} -} +} \ No newline at end of file From 92506489f99dabe934586962ecf20e46d3343536 Mon Sep 17 00:00:00 2001 From: PhysX Date: Fri, 7 Aug 2026 01:17:19 +0200 Subject: [PATCH 2/6] Refactor Discord command registration and enhance ticket creation logic --- build.gradle.kts | 1 + src/main/java/org/ares/Main.java | 23 ++++++++++++++++--- .../org/ares/commands/CommandRegistry.java | 4 ++-- .../listeners/tickets/TicketListener.java | 13 ++++++++--- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 5803241..a5b721d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,6 +13,7 @@ dependencies { implementation("com.discord4j:discord4j-core:3.3.2") implementation("org.apache.logging.log4j:log4j:2.17.1") implementation("org.apache.logging.log4j:log4j-api:2.17.1") + implementation("ch.qos.logback:logback-classic:1.5.6") } tasks.test { diff --git a/src/main/java/org/ares/Main.java b/src/main/java/org/ares/Main.java index 0f2a6b0..54977f2 100644 --- a/src/main/java/org/ares/Main.java +++ b/src/main/java/org/ares/Main.java @@ -3,24 +3,41 @@ import discord4j.core.DiscordClient; import discord4j.core.GatewayDiscordClient; import discord4j.core.event.domain.channel.TextChannelCreateEvent; +import discord4j.core.event.domain.command.ApplicationCommandEvent; import discord4j.core.event.domain.interaction.ButtonInteractionEvent; +import discord4j.core.event.domain.lifecycle.ReadyEvent; +import discord4j.core.object.entity.User; import discord4j.core.object.presence.ClientActivity; import discord4j.core.object.presence.ClientPresence; import discord4j.rest.RestClient; -import io.netty.handler.ssl.ClientAuth; + import org.ares.commands.CommandRegistry; import org.ares.listeners.ListenerRegistry; import org.ares.listeners.tickets.TicketCloseListener; import org.ares.listeners.tickets.TicketListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static org.ares.listeners.tickets.TicketListener.createTicketSalon; public class Main { + private static final Logger logger = LoggerFactory.getLogger(Main.class); + public static void main(String[] args) { DiscordClient client = DiscordClient.create(System.getenv("BOT_TOKEN")); // Créez une variable d'environement au lancement appelé "BOT_TOKEN". GatewayDiscordClient gateway = client.login().block(); - ClientPresence.online(ClientActivity.streaming("Regarde ClicDroit", "https://twitch.tv/")); + + + gateway.getEventDispatcher().on(ReadyEvent.class) + .subscribe(readyEvent -> { + User self = readyEvent.getSelf(); + logger.info("%s connecté !" + self.getUsername()); + self.getClient().updatePresence(ClientPresence.online( + ClientActivity.streaming("Regarde ClicDroit", "https://twitch.tv/") + )); + }); + // Listeners des events bouton et autres. gateway.on(ButtonInteractionEvent.class, event -> @@ -37,7 +54,7 @@ public static void main(String[] args) { // Registery des commandes slash. CommandRegistry registry = new CommandRegistry(); - registry.registerToDiscord(RestClient.create(client.getCoreResources().getToken()), 1396773019690729524L); + registry.registerToDiscord(RestClient.create(client.getCoreResources().getToken())); registry.listenTo(gateway); // Registery des différente écoute, MemberJoin etc. diff --git a/src/main/java/org/ares/commands/CommandRegistry.java b/src/main/java/org/ares/commands/CommandRegistry.java index 25f576c..74ca256 100644 --- a/src/main/java/org/ares/commands/CommandRegistry.java +++ b/src/main/java/org/ares/commands/CommandRegistry.java @@ -25,7 +25,7 @@ public ISlashCommand getCommand(String name) { return commands.get(name); } - public void registerToDiscord(RestClient restClient, long guildId) { + public void registerToDiscord(RestClient restClient) { long applicationId = restClient.getApplicationId().block(); List requests = commands.values() @@ -34,7 +34,7 @@ public void registerToDiscord(RestClient restClient, long guildId) { .toList(); restClient.getApplicationService() - .bulkOverwriteGuildApplicationCommand(applicationId, guildId, requests) + .bulkOverwriteGlobalApplicationCommand(applicationId, requests) .subscribe(); } diff --git a/src/main/java/org/ares/listeners/tickets/TicketListener.java b/src/main/java/org/ares/listeners/tickets/TicketListener.java index 2c03c91..e0356c5 100644 --- a/src/main/java/org/ares/listeners/tickets/TicketListener.java +++ b/src/main/java/org/ares/listeners/tickets/TicketListener.java @@ -6,6 +6,7 @@ import discord4j.core.object.PermissionOverwrite; import discord4j.core.object.component.*; import discord4j.core.object.entity.Guild; +import discord4j.core.object.entity.channel.Category; import discord4j.core.spec.EmbedCreateSpec; import discord4j.core.spec.MessageCreateSpec; import discord4j.core.spec.TextChannelCreateSpec; @@ -23,14 +24,20 @@ public class TicketListener { public static Mono createTicketSalon(ButtonInteractionEvent event) { Guild guild = event.getInteraction().getGuild().block(); - var categoryId = 1534193855363289159L; - assert guild != null; + Category category = guild.getChannels() + .ofType(Category.class) + .filter(cat -> cat.getName().equalsIgnoreCase("\uD83C\uDFAB Tickets")) + .next() + .block(); + if (category == null) { + return event.reply("La catégorie 'Ticket' n'existe pas sur ce serveur !").withEphemeral(true); + } if (tickets.containsValue(event.getUser().getUsername())) { return event.reply("Vous avez déja un ticket d'ouvert !").withEphemeral(true); } else { return guild.createTextChannel(TextChannelCreateSpec.builder() .name("ticket-" + event.getUser().getUsername()) - .parentId(Snowflake.of(categoryId)) + .parentId(category.getId()) .permissionOverwrites(Set.of( PermissionOverwrite.forRole( guild.getId(), From b599f80b11e4c7d32a73b2dad22ed11a9abe3b8b Mon Sep 17 00:00:00 2001 From: PhysX Date: Fri, 7 Aug 2026 01:24:05 +0200 Subject: [PATCH 3/6] Make Gradle wrapper executable in Jenkins build stage --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 8310015..a3d05e2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -4,6 +4,7 @@ pipeline { stages { stage('Build') { steps { + sh 'chmod +x ./gradlew' sh './gradlew build' } } From d39f81be3c2e6597ee84f0c1ad59077374796cd0 Mon Sep 17 00:00:00 2001 From: PhysX Date: Fri, 7 Aug 2026 01:39:04 +0200 Subject: [PATCH 4/6] Update Jenkinsfile and build.gradle.kts for Docker integration and jar task configuration --- Jenkinsfile | 12 ++++++------ build.gradle.kts | 11 ++++++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index a3d05e2..dad612e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,7 +5,7 @@ pipeline { stage('Build') { steps { sh 'chmod +x ./gradlew' - sh './gradlew build' + sh './gradlew jar' } } @@ -22,9 +22,9 @@ pipeline { } steps { sh ''' - docker stop bot-preprod || true - docker rm bot-preprod || true - docker run -d --name bot-preprod \ + docker stop ares-preprod || true + docker rm ares-preprod || true + docker run -d --name ares-preprod \ -e BOT_TOKEN=$DISCORD_TOKEN \ ares-bot:develop ''' @@ -38,8 +38,8 @@ pipeline { } steps { sh ''' - docker stop bot-prod || true - docker rm bot-prod || true + docker stop ares-prod || true + docker rm ares-prod || true docker run -d --name bot-prod \ -e BOT_TOKEN=$DISCORD_TOKEN \ ares-bot:master diff --git a/build.gradle.kts b/build.gradle.kts index a5b721d..4f72b4c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,14 @@ plugins { - id("java") + java + id("com.github.johnrengelman.shadow") version "8.1.1" +} + +tasks { + jar { + manifest { + attributes["Main-Class"] = "org.ares.Main" // remplace par ton vrai chemin de classe + } + } } group = "org.ares" From d489342d43c22b8152ffee87a63fc45e33b40840 Mon Sep 17 00:00:00 2001 From: PhysX Date: Fri, 7 Aug 2026 01:43:56 +0200 Subject: [PATCH 5/6] Update shadow plugin version and adjust Dockerfile for all jar packaging --- Dockerfile | 2 +- build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index f2d311f..ea352ed 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ FROM eclipse-temurin:21-jre WORKDIR /app -COPY build/libs/ClicBot-1.0-SNAPSHOT.jar app.jar +COPY build/libs/ClicBot-1.0-SNAPSHOT-all.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 4f72b4c..4d38196 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("com.github.johnrengelman.shadow") version "8.1.1" + id("com.gradleup.shadow") version "8.3.5" } tasks { From 15d8f2949b64287e7c1ff006c6db0f39a6fa4a79 Mon Sep 17 00:00:00 2001 From: PhysX Date: Fri, 7 Aug 2026 01:45:57 +0200 Subject: [PATCH 6/6] Update Jenkinsfile to use shadowJar for building artifacts --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index dad612e..f887227 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,7 +5,7 @@ pipeline { stage('Build') { steps { sh 'chmod +x ./gradlew' - sh './gradlew jar' + sh './gradlew shadowJar' } }