From 9f34993a0d27a3bdd442b3104987a118ac7f4378 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Tue, 9 Jan 2024 21:28:56 +0100 Subject: [PATCH 01/58] Update role sync management --- .../discord/services/RoleSyncService.java | 68 +++++++++++++------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/src/main/java/net/turniptales/discord/services/RoleSyncService.java b/src/main/java/net/turniptales/discord/services/RoleSyncService.java index a80b172..6fe6892 100644 --- a/src/main/java/net/turniptales/discord/services/RoleSyncService.java +++ b/src/main/java/net/turniptales/discord/services/RoleSyncService.java @@ -7,8 +7,6 @@ import org.springframework.stereotype.Component; import java.time.OffsetDateTime; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Timer; import java.util.TimerTask; @@ -16,29 +14,60 @@ import static java.lang.System.currentTimeMillis; import static java.util.concurrent.TimeUnit.HOURS; +import static net.turniptales.discord.Config.ROLE_0; +import static net.turniptales.discord.Config.ROLE_1_MONTH; +import static net.turniptales.discord.Config.ROLE_1_WEEK; +import static net.turniptales.discord.Config.ROLE_1_YEAR; +import static net.turniptales.discord.Config.ROLE_2_WEEK; +import static net.turniptales.discord.Config.ROLE_2_YEAR; +import static net.turniptales.discord.Config.ROLE_3_MONTH; +import static net.turniptales.discord.Config.ROLE_3_YEAR; +import static net.turniptales.discord.Config.ROLE_6_MONTH; @Log4j2 @Component public class RoleSyncService { + private List stayRoles; + public RoleSyncService() { long sixHoursInMillis = HOURS.toMillis(6); new Timer().scheduleAtFixedRate(new TimerTask() { @Override public void run() { + assert ROLE_0 != null; + assert ROLE_1_WEEK != null; + assert ROLE_2_WEEK != null; + assert ROLE_1_MONTH != null; + assert ROLE_3_MONTH != null; + assert ROLE_6_MONTH != null; + assert ROLE_1_YEAR != null; + assert ROLE_2_YEAR != null; + assert ROLE_3_YEAR != null; + RoleSyncService.this.stayRoles = List.of(ROLE_0, ROLE_1_WEEK, ROLE_2_WEEK, ROLE_1_MONTH, ROLE_3_MONTH, ROLE_6_MONTH, ROLE_1_YEAR, ROLE_2_YEAR, ROLE_3_YEAR); + long startTime = currentTimeMillis(); log.info("Discord role synchronising: started"); Guild guild = Config.GUILD; assert guild != null; - guild.loadMembers().get().forEach(member -> getRolesUserShouldHave(member.getTimeJoined()).stream() - .filter(role -> !member.getRoles().contains(role)) - .forEach(role -> { - guild.addRoleToMember(member, role).queue(); - log.info("Discord role synchronising: Add role {} to member {}", role.getName(), member.getEffectiveName()); - })); + guild.loadMembers().get().forEach(member -> { + Role highestRoleUserShouldHave = getHighestRoleUserShouldHave(member.getTimeJoined()); + RoleSyncService.this.stayRoles.stream() + .filter(role -> !role.equals(highestRoleUserShouldHave)) + .filter(role -> member.getRoles().contains(role)) + .forEach(role -> { + guild.removeRoleFromMember(member, role).queue(); + log.info("Discord role synchronising: Remove role {} from member {}", role.getName(), member.getEffectiveName()); + }); + + if (!member.getRoles().contains(highestRoleUserShouldHave)) { + guild.addRoleToMember(member, highestRoleUserShouldHave).queue(); + log.info("Discord role synchronising: Add role {} to member {}", highestRoleUserShouldHave.getName(), member.getEffectiveName()); + } + }); log.info("Discord role synchronising: finished in {}ms", currentTimeMillis() - startTime); } @@ -46,45 +75,44 @@ public void run() { log.info("Discord role synchronising: scheduled"); } - private Collection getRolesUserShouldHave(OffsetDateTime timeJoined) { - assert Config.ROLE_0 != null; - Collection roles = new ArrayList<>(List.of(Config.ROLE_0)); + private Role getHighestRoleUserShouldHave(OffsetDateTime timeJoined) { + Role role = ROLE_0; long joinTimeInMillis = timeJoined.toInstant().toEpochMilli(); long currentTimeInMillis = currentTimeMillis(); if (joinTimeInMillis + TimeUnit.DAYS.toMillis(7) <= currentTimeInMillis) { // 1 Woche - roles.add(Config.ROLE_1_WEEK); + role = Config.ROLE_1_WEEK; } if (joinTimeInMillis + TimeUnit.DAYS.toMillis(14) <= currentTimeInMillis) { // 2 Wochen - roles.add(Config.ROLE_2_WEEK); + role = Config.ROLE_2_WEEK; } if (joinTimeInMillis + TimeUnit.DAYS.toMillis(30) <= currentTimeInMillis) { // 1 Monat - roles.add(Config.ROLE_1_MONTH); + role = Config.ROLE_1_MONTH; } if (joinTimeInMillis + TimeUnit.DAYS.toMillis(90) <= currentTimeInMillis) { // 3 Monate - roles.add(Config.ROLE_3_MONTH); + role = Config.ROLE_3_MONTH; } if (joinTimeInMillis + TimeUnit.DAYS.toMillis(180) <= currentTimeInMillis) { // 6 Monate - roles.add(Config.ROLE_6_MONTH); + role = Config.ROLE_6_MONTH; } if (joinTimeInMillis + TimeUnit.DAYS.toMillis(365) <= currentTimeInMillis) { // 1 Jahr - roles.add(Config.ROLE_1_YEAR); + role = Config.ROLE_1_YEAR; } if (joinTimeInMillis + TimeUnit.DAYS.toMillis(730) <= currentTimeInMillis) { // 2 Jahre - roles.add(Config.ROLE_2_YEAR); + role = Config.ROLE_2_YEAR; } if (joinTimeInMillis + TimeUnit.DAYS.toMillis(1460) <= currentTimeInMillis) { // 3 Jahre - roles.add(Config.ROLE_3_YEAR); + role = Config.ROLE_3_YEAR; } - return roles; + return role; } } From f3f9ce7817461400b5546f73649dddde912c69aa Mon Sep 17 00:00:00 2001 From: rettichlp Date: Tue, 9 Jan 2024 21:29:40 +0100 Subject: [PATCH 02/58] Update output file naming --- .github/workflows/release.yml | 2 +- Dockerfile | 4 ++-- pom.xml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f1cf653..bc63217 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,4 +22,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: Artifacts - path: target/discord-1.0.0.jar \ No newline at end of file + path: target/turniptales-discord.jar \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index d76a4c7..a318fe7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,6 @@ FROM openjdk:17 WORKDIR /app -COPY discord.jar /app/discord.jar +COPY turniptales-discord.jar /app/turniptales-discord.jar -CMD ["java", "-jar", "discord.jar"] \ No newline at end of file +CMD ["java", "-jar", "turniptales-discord.jar"] \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2fdd400..b0d3e10 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ org.apache.tomcat.embed tomcat-embed-core - 11.0.0-M15 + 10.1.17 @@ -77,7 +77,7 @@ - discord + turniptales-discord org.springframework.boot From 8af2ea5ddeadfc2519f65326b4402c2343f8ea00 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Tue, 9 Jan 2024 21:29:55 +0100 Subject: [PATCH 03/58] Remove ssl from application.properties --- src/main/resources/application.properties | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 59a4293..354888b 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,13 +1,4 @@ server.port=9000 -server.ssl.enabled=true -# The format used for the keystore. It could be set to JKS in case it is a JKS file -server.ssl.key-store-type=PKCS12 -# The path to the keystore containing the certificate -server.ssl.key-store=classpath:keystore/unicacityaddon.p12 -# The password used to generate the certificate -server.ssl.key-store-password=d8d8ab09ac4c457d68489c1840567fa640befbed -# The alias mapped to the certificate -server.ssl.key-password=d8d8ab09ac4c457d68489c1840567fa640befbed server.error.path=/error server.error.whitelabel.enabled=false spring.main.banner-mode=off From 2087c9148018399f0f4205b9f81a8f1b817ee376 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Wed, 10 Jan 2024 00:35:39 +0100 Subject: [PATCH 04/58] Rename main class files --- src/main/java/net/turniptales/discord/Config.java | 2 +- .../discord/{Application.java => TurniptalesDiscord.java} | 4 ++-- .../net/turniptales/discord/services/ActivitySyncService.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/main/java/net/turniptales/discord/{Application.java => TurniptalesDiscord.java} (96%) diff --git a/src/main/java/net/turniptales/discord/Config.java b/src/main/java/net/turniptales/discord/Config.java index 30b429d..b5585b8 100644 --- a/src/main/java/net/turniptales/discord/Config.java +++ b/src/main/java/net/turniptales/discord/Config.java @@ -6,7 +6,7 @@ import net.dv8tion.jda.api.entities.channel.concrete.Category; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import static net.turniptales.discord.Application.TURNIPTALES_BOT; +import static net.turniptales.discord.TurniptalesDiscord.TURNIPTALES_BOT; public class Config { diff --git a/src/main/java/net/turniptales/discord/Application.java b/src/main/java/net/turniptales/discord/TurniptalesDiscord.java similarity index 96% rename from src/main/java/net/turniptales/discord/Application.java rename to src/main/java/net/turniptales/discord/TurniptalesDiscord.java index be85a42..9de79bc 100644 --- a/src/main/java/net/turniptales/discord/Application.java +++ b/src/main/java/net/turniptales/discord/TurniptalesDiscord.java @@ -24,12 +24,12 @@ @Log4j2 @SpringBootApplication -public class Application implements WebMvcConfigurer { +public class TurniptalesDiscord implements WebMvcConfigurer { public static JDA TURNIPTALES_BOT; public static void main(String[] args) { - SpringApplication.run(Application.class, args); + SpringApplication.run(TurniptalesDiscord.class, args); long discordBotStartTime = currentTimeMillis(); log.info("Discord bot starting"); diff --git a/src/main/java/net/turniptales/discord/services/ActivitySyncService.java b/src/main/java/net/turniptales/discord/services/ActivitySyncService.java index f28a9e0..771a07b 100644 --- a/src/main/java/net/turniptales/discord/services/ActivitySyncService.java +++ b/src/main/java/net/turniptales/discord/services/ActivitySyncService.java @@ -2,7 +2,7 @@ import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Activity; -import net.turniptales.discord.Application; +import net.turniptales.discord.TurniptalesDiscord; import org.springframework.stereotype.Component; import java.util.Timer; @@ -26,7 +26,7 @@ public void run() { log.info("Activity synchronising: started"); Activity activity = playing("auf TurnipTales.net"); - Application.TURNIPTALES_BOT.getPresence().setActivity(activity); + TurniptalesDiscord.TURNIPTALES_BOT.getPresence().setActivity(activity); log.info("Activity synchronising: finished in {}ms", currentTimeMillis() - startTime); } From 9102bc589c0d2b87dedb9ad2288cf9e787d90e6d Mon Sep 17 00:00:00 2001 From: rettichlp Date: Wed, 10 Jan 2024 00:47:55 +0100 Subject: [PATCH 05/58] Rename project name in pom --- pom.xml | 3 ++- src/main/java/net/turniptales/discord/Config.java | 2 +- .../{TurniptalesDiscord.java => TurnipTalesDiscord.java} | 4 ++-- .../net/turniptales/discord/services/ActivitySyncService.java | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) rename src/main/java/net/turniptales/discord/{TurniptalesDiscord.java => TurnipTalesDiscord.java} (96%) diff --git a/pom.xml b/pom.xml index b0d3e10..f1354f2 100644 --- a/pom.xml +++ b/pom.xml @@ -14,12 +14,13 @@ 1.0.0 jar - Discord + TurnipTales-Discord Discord application of TurnipTales 17 17 + UTF-8 diff --git a/src/main/java/net/turniptales/discord/Config.java b/src/main/java/net/turniptales/discord/Config.java index b5585b8..c4e024d 100644 --- a/src/main/java/net/turniptales/discord/Config.java +++ b/src/main/java/net/turniptales/discord/Config.java @@ -6,7 +6,7 @@ import net.dv8tion.jda.api.entities.channel.concrete.Category; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import static net.turniptales.discord.TurniptalesDiscord.TURNIPTALES_BOT; +import static net.turniptales.discord.TurnipTalesDiscord.TURNIPTALES_BOT; public class Config { diff --git a/src/main/java/net/turniptales/discord/TurniptalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java similarity index 96% rename from src/main/java/net/turniptales/discord/TurniptalesDiscord.java rename to src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index 9de79bc..34f1f8c 100644 --- a/src/main/java/net/turniptales/discord/TurniptalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -24,12 +24,12 @@ @Log4j2 @SpringBootApplication -public class TurniptalesDiscord implements WebMvcConfigurer { +public class TurnipTalesDiscord implements WebMvcConfigurer { public static JDA TURNIPTALES_BOT; public static void main(String[] args) { - SpringApplication.run(TurniptalesDiscord.class, args); + SpringApplication.run(TurnipTalesDiscord.class, args); long discordBotStartTime = currentTimeMillis(); log.info("Discord bot starting"); diff --git a/src/main/java/net/turniptales/discord/services/ActivitySyncService.java b/src/main/java/net/turniptales/discord/services/ActivitySyncService.java index 771a07b..0e42985 100644 --- a/src/main/java/net/turniptales/discord/services/ActivitySyncService.java +++ b/src/main/java/net/turniptales/discord/services/ActivitySyncService.java @@ -2,7 +2,7 @@ import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Activity; -import net.turniptales.discord.TurniptalesDiscord; +import net.turniptales.discord.TurnipTalesDiscord; import org.springframework.stereotype.Component; import java.util.Timer; @@ -26,7 +26,7 @@ public void run() { log.info("Activity synchronising: started"); Activity activity = playing("auf TurnipTales.net"); - TurniptalesDiscord.TURNIPTALES_BOT.getPresence().setActivity(activity); + TurnipTalesDiscord.TURNIPTALES_BOT.getPresence().setActivity(activity); log.info("Activity synchronising: finished in {}ms", currentTimeMillis() - startTime); } From 63d994ee287bed43a48855167582c6b1d9835baa Mon Sep 17 00:00:00 2001 From: rettichlp Date: Wed, 10 Jan 2024 20:45:48 +0100 Subject: [PATCH 06/58] Refactor api model package names --- .../java/net/turniptales/discord/commands/StatsCommand.java | 4 ++-- .../net/turniptales/discord/commands/VerifyCommand.java | 4 ++-- .../java/net/turniptales/discord/{ => common}/api/API.java | 6 +++--- .../{api/schema => common/api/model}/PlayerStats.java | 2 +- .../{api/schema => common/api/model}/Verification.java | 2 +- .../discord/{ => common}/services/ActivitySyncService.java | 2 +- .../discord/{ => common}/services/RoleSyncService.java | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) rename src/main/java/net/turniptales/discord/{ => common}/api/API.java (76%) rename src/main/java/net/turniptales/discord/{api/schema => common/api/model}/PlayerStats.java (83%) rename src/main/java/net/turniptales/discord/{api/schema => common/api/model}/Verification.java (80%) rename src/main/java/net/turniptales/discord/{ => common}/services/ActivitySyncService.java (96%) rename src/main/java/net/turniptales/discord/{ => common}/services/RoleSyncService.java (98%) diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index b6bc6a2..4e97af6 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -6,8 +6,8 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; -import net.turniptales.discord.api.API; -import net.turniptales.discord.api.schema.PlayerStats; +import net.turniptales.discord.common.api.API; +import net.turniptales.discord.common.api.model.PlayerStats; import static java.lang.String.valueOf; import static java.util.Objects.nonNull; diff --git a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java index ec041a5..3ad7b6b 100644 --- a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java @@ -3,12 +3,12 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; -import net.turniptales.discord.api.schema.Verification; +import net.turniptales.discord.common.api.model.Verification; import static java.util.Objects.nonNull; import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.SECONDS; -import static net.turniptales.discord.api.API.getVerification; +import static net.turniptales.discord.common.api.API.getVerification; public class VerifyCommand extends ListenerAdapter { diff --git a/src/main/java/net/turniptales/discord/api/API.java b/src/main/java/net/turniptales/discord/common/api/API.java similarity index 76% rename from src/main/java/net/turniptales/discord/api/API.java rename to src/main/java/net/turniptales/discord/common/api/API.java index 80567e9..1a0b9bf 100644 --- a/src/main/java/net/turniptales/discord/api/API.java +++ b/src/main/java/net/turniptales/discord/common/api/API.java @@ -1,7 +1,7 @@ -package net.turniptales.discord.api; +package net.turniptales.discord.common.api; -import net.turniptales.discord.api.schema.PlayerStats; -import net.turniptales.discord.api.schema.Verification; +import net.turniptales.discord.common.api.model.PlayerStats; +import net.turniptales.discord.common.api.model.Verification; import static java.util.UUID.fromString; diff --git a/src/main/java/net/turniptales/discord/api/schema/PlayerStats.java b/src/main/java/net/turniptales/discord/common/api/model/PlayerStats.java similarity index 83% rename from src/main/java/net/turniptales/discord/api/schema/PlayerStats.java rename to src/main/java/net/turniptales/discord/common/api/model/PlayerStats.java index 7c6f423..5c5414e 100644 --- a/src/main/java/net/turniptales/discord/api/schema/PlayerStats.java +++ b/src/main/java/net/turniptales/discord/common/api/model/PlayerStats.java @@ -1,4 +1,4 @@ -package net.turniptales.discord.api.schema; +package net.turniptales.discord.common.api.model; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/src/main/java/net/turniptales/discord/api/schema/Verification.java b/src/main/java/net/turniptales/discord/common/api/model/Verification.java similarity index 80% rename from src/main/java/net/turniptales/discord/api/schema/Verification.java rename to src/main/java/net/turniptales/discord/common/api/model/Verification.java index 7cf2eb4..4e051a0 100644 --- a/src/main/java/net/turniptales/discord/api/schema/Verification.java +++ b/src/main/java/net/turniptales/discord/common/api/model/Verification.java @@ -1,4 +1,4 @@ -package net.turniptales.discord.api.schema; +package net.turniptales.discord.common.api.model; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/src/main/java/net/turniptales/discord/services/ActivitySyncService.java b/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java similarity index 96% rename from src/main/java/net/turniptales/discord/services/ActivitySyncService.java rename to src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java index 0e42985..38fcb8e 100644 --- a/src/main/java/net/turniptales/discord/services/ActivitySyncService.java +++ b/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java @@ -1,4 +1,4 @@ -package net.turniptales.discord.services; +package net.turniptales.discord.common.services; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Activity; diff --git a/src/main/java/net/turniptales/discord/services/RoleSyncService.java b/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java similarity index 98% rename from src/main/java/net/turniptales/discord/services/RoleSyncService.java rename to src/main/java/net/turniptales/discord/common/services/RoleSyncService.java index 6fe6892..db292b7 100644 --- a/src/main/java/net/turniptales/discord/services/RoleSyncService.java +++ b/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java @@ -1,4 +1,4 @@ -package net.turniptales.discord.services; +package net.turniptales.discord.common.services; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Guild; From cf5b0b254504374964148968da0af20e259e89ce Mon Sep 17 00:00:00 2001 From: rettichlp Date: Sun, 14 Jan 2024 22:50:59 +0100 Subject: [PATCH 07/58] Reformat code --- .../java/net/turniptales/discord/commands/StatsCommand.java | 4 +++- .../java/net/turniptales/discord/commands/TicketCommand.java | 3 ++- .../java/net/turniptales/discord/commands/VerifyCommand.java | 4 +++- .../net/turniptales/discord/events/GuildBanEventHandler.java | 4 +++- .../discord/events/GuildMemberJoinEventHandler.java | 4 +++- .../discord/events/GuildMemberRemoveEventHandler.java | 4 +++- 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index 4e97af6..f7873b8 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -17,7 +17,9 @@ public class StatsCommand extends ListenerAdapter { @Override public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { - if (!e.getName().equals("stats")) return; + if (!e.getName().equals("stats")) { + return; + } OptionMapping playerOptionMapping = e.getOption("player"); if (!nonNull(playerOptionMapping)) { diff --git a/src/main/java/net/turniptales/discord/commands/TicketCommand.java b/src/main/java/net/turniptales/discord/commands/TicketCommand.java index 74c07c0..0ecbaac 100644 --- a/src/main/java/net/turniptales/discord/commands/TicketCommand.java +++ b/src/main/java/net/turniptales/discord/commands/TicketCommand.java @@ -16,8 +16,9 @@ public class TicketCommand extends ListenerAdapter { @Override public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { - if (!e.getName().equals("ticket") || !Objects.requireNonNull(e.getMember()).hasPermission(ADMINISTRATOR)) + if (!e.getName().equals("ticket") || !Objects.requireNonNull(e.getMember()).hasPermission(ADMINISTRATOR)) { return; + } e.deferReply(true).queue(); EmbedBuilder embedBuilder = new EmbedBuilder() diff --git a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java index 3ad7b6b..8bee8dc 100644 --- a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java @@ -14,7 +14,9 @@ public class VerifyCommand extends ListenerAdapter { @Override public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { - if (!e.getName().equals("verify")) return; + if (!e.getName().equals("verify")) { + return; + } OptionMapping codeOptionMapping = e.getOption("code"); if (!nonNull(codeOptionMapping)) { diff --git a/src/main/java/net/turniptales/discord/events/GuildBanEventHandler.java b/src/main/java/net/turniptales/discord/events/GuildBanEventHandler.java index 8dfe0bb..7b7f6a9 100644 --- a/src/main/java/net/turniptales/discord/events/GuildBanEventHandler.java +++ b/src/main/java/net/turniptales/discord/events/GuildBanEventHandler.java @@ -15,7 +15,9 @@ public class GuildBanEventHandler extends ListenerAdapter { public void onGuildBan(GuildBanEvent e) { Guild guild = e.getGuild(); TextChannel systemChannel = guild.getSystemChannel(); - if (systemChannel == null) return; + if (systemChannel == null) { + return; + } User user = e.getUser(); int memberCount = guild.getMemberCount(); diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java b/src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java index 6349708..7537d97 100644 --- a/src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java +++ b/src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java @@ -16,7 +16,9 @@ public class GuildMemberJoinEventHandler extends ListenerAdapter { public void onGuildMemberJoin(GuildMemberJoinEvent e) { Guild guild = e.getGuild(); TextChannel systemChannel = guild.getSystemChannel(); - if (systemChannel == null) return; + if (systemChannel == null) { + return; + } User user = e.getUser(); int memberCount = guild.getMemberCount(); diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java b/src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java index ae9cb77..11f0450 100644 --- a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java +++ b/src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java @@ -16,7 +16,9 @@ public class GuildMemberRemoveEventHandler extends ListenerAdapter { public void onGuildMemberRemove(GuildMemberRemoveEvent e) { Guild guild = e.getGuild(); TextChannel systemChannel = Config.SYSTEM_TEXT_CHANNEL; - if (systemChannel == null) return; + if (systemChannel == null) { + return; + } User user = e.getUser(); int memberCount = guild.getMemberCount(); From daee38d94e33d0c490933871f5d04310cfa89004 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Mon, 15 Jan 2024 18:39:44 +0100 Subject: [PATCH 08/58] Optimize static imports and reformat code --- .../common/services/ActivitySyncService.java | 8 ++-- .../common/services/RoleSyncService.java | 38 +++++++++---------- .../events/GuildMemberJoinEventHandler.java | 6 +-- .../events/GuildMemberRemoveEventHandler.java | 4 +- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java b/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java index 38fcb8e..b82de04 100644 --- a/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java +++ b/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java @@ -2,22 +2,22 @@ import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Activity; -import net.turniptales.discord.TurnipTalesDiscord; import org.springframework.stereotype.Component; import java.util.Timer; import java.util.TimerTask; -import java.util.concurrent.TimeUnit; import static java.lang.System.currentTimeMillis; +import static java.util.concurrent.TimeUnit.MINUTES; import static net.dv8tion.jda.api.entities.Activity.playing; +import static net.turniptales.discord.TurnipTalesDiscord.TURNIPTALES_BOT; @Log4j2 @Component public class ActivitySyncService { public ActivitySyncService() { - long tenMinutesInMillis = TimeUnit.MINUTES.toMillis(10); + long tenMinutesInMillis = MINUTES.toMillis(10); new Timer().scheduleAtFixedRate(new TimerTask() { @Override @@ -26,7 +26,7 @@ public void run() { log.info("Activity synchronising: started"); Activity activity = playing("auf TurnipTales.net"); - TurnipTalesDiscord.TURNIPTALES_BOT.getPresence().setActivity(activity); + TURNIPTALES_BOT.getPresence().setActivity(activity); log.info("Activity synchronising: finished in {}ms", currentTimeMillis() - startTime); } diff --git a/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java b/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java index db292b7..4cdee41 100644 --- a/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java +++ b/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java @@ -3,17 +3,17 @@ import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Role; -import net.turniptales.discord.Config; import org.springframework.stereotype.Component; import java.time.OffsetDateTime; import java.util.List; import java.util.Timer; import java.util.TimerTask; -import java.util.concurrent.TimeUnit; import static java.lang.System.currentTimeMillis; +import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.HOURS; +import static net.turniptales.discord.Config.GUILD; import static net.turniptales.discord.Config.ROLE_0; import static net.turniptales.discord.Config.ROLE_1_MONTH; import static net.turniptales.discord.Config.ROLE_1_WEEK; @@ -50,7 +50,7 @@ public void run() { long startTime = currentTimeMillis(); log.info("Discord role synchronising: started"); - Guild guild = Config.GUILD; + Guild guild = GUILD; assert guild != null; guild.loadMembers().get().forEach(member -> { @@ -81,36 +81,36 @@ private Role getHighestRoleUserShouldHave(OffsetDateTime timeJoined) { long joinTimeInMillis = timeJoined.toInstant().toEpochMilli(); long currentTimeInMillis = currentTimeMillis(); - if (joinTimeInMillis + TimeUnit.DAYS.toMillis(7) <= currentTimeInMillis) { // 1 Woche - role = Config.ROLE_1_WEEK; + if (joinTimeInMillis + DAYS.toMillis(7) <= currentTimeInMillis) { // 1 Woche + role = ROLE_1_WEEK; } - if (joinTimeInMillis + TimeUnit.DAYS.toMillis(14) <= currentTimeInMillis) { // 2 Wochen - role = Config.ROLE_2_WEEK; + if (joinTimeInMillis + DAYS.toMillis(14) <= currentTimeInMillis) { // 2 Wochen + role = ROLE_2_WEEK; } - if (joinTimeInMillis + TimeUnit.DAYS.toMillis(30) <= currentTimeInMillis) { // 1 Monat - role = Config.ROLE_1_MONTH; + if (joinTimeInMillis + DAYS.toMillis(30) <= currentTimeInMillis) { // 1 Monat + role = ROLE_1_MONTH; } - if (joinTimeInMillis + TimeUnit.DAYS.toMillis(90) <= currentTimeInMillis) { // 3 Monate - role = Config.ROLE_3_MONTH; + if (joinTimeInMillis + DAYS.toMillis(90) <= currentTimeInMillis) { // 3 Monate + role = ROLE_3_MONTH; } - if (joinTimeInMillis + TimeUnit.DAYS.toMillis(180) <= currentTimeInMillis) { // 6 Monate - role = Config.ROLE_6_MONTH; + if (joinTimeInMillis + DAYS.toMillis(180) <= currentTimeInMillis) { // 6 Monate + role = ROLE_6_MONTH; } - if (joinTimeInMillis + TimeUnit.DAYS.toMillis(365) <= currentTimeInMillis) { // 1 Jahr - role = Config.ROLE_1_YEAR; + if (joinTimeInMillis + DAYS.toMillis(365) <= currentTimeInMillis) { // 1 Jahr + role = ROLE_1_YEAR; } - if (joinTimeInMillis + TimeUnit.DAYS.toMillis(730) <= currentTimeInMillis) { // 2 Jahre - role = Config.ROLE_2_YEAR; + if (joinTimeInMillis + DAYS.toMillis(730) <= currentTimeInMillis) { // 2 Jahre + role = ROLE_2_YEAR; } - if (joinTimeInMillis + TimeUnit.DAYS.toMillis(1460) <= currentTimeInMillis) { // 3 Jahre - role = Config.ROLE_3_YEAR; + if (joinTimeInMillis + DAYS.toMillis(1460) <= currentTimeInMillis) { // 3 Jahre + role = ROLE_3_YEAR; } return role; diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java b/src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java index 7537d97..157c987 100644 --- a/src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java +++ b/src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java @@ -6,9 +6,9 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.turniptales.discord.Config; import static java.awt.Color.GREEN; +import static net.turniptales.discord.Config.ROLE_0; public class GuildMemberJoinEventHandler extends ListenerAdapter { @@ -32,7 +32,7 @@ public void onGuildMemberJoin(GuildMemberJoinEvent e) { systemChannel.sendMessageEmbeds(embedBuilder.build()).queue(); systemChannel.getManager().setTopic("Aktuelle Spieler: " + memberCount).queue(); - assert Config.ROLE_0 != null; - guild.addRoleToMember(user, Config.ROLE_0).queue(); + assert ROLE_0 != null; + guild.addRoleToMember(user, ROLE_0).queue(); } } diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java b/src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java index 11f0450..55da83e 100644 --- a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java +++ b/src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java @@ -6,16 +6,16 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.turniptales.discord.Config; import static java.awt.Color.ORANGE; +import static net.turniptales.discord.Config.SYSTEM_TEXT_CHANNEL; public class GuildMemberRemoveEventHandler extends ListenerAdapter { @Override public void onGuildMemberRemove(GuildMemberRemoveEvent e) { Guild guild = e.getGuild(); - TextChannel systemChannel = Config.SYSTEM_TEXT_CHANNEL; + TextChannel systemChannel = SYSTEM_TEXT_CHANNEL; if (systemChannel == null) { return; } From c13a8bc1d381af8ebc5213822d9720de6c250cc3 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Sun, 21 Jan 2024 18:03:00 +0100 Subject: [PATCH 09/58] Update VerifyCommand and StatsCommand --- .../java/net/turniptales/discord/Config.java | 3 +- .../discord/TurnipTalesDiscord.java | 5 +- .../discord/commands/StatsCommand.java | 120 ++++++++++++++++-- .../discord/commands/VerifyCommand.java | 15 ++- .../turniptales/discord/common/api/API.java | 18 --- .../turniptales/discord/common/api/Api.java | 47 +++++++ .../discord/common/api/model/PlayerStats.java | 12 ++ .../common/api/model/Verification.java | 14 -- .../common/api/model/stats/Contract.java | 21 +++ .../api/model/stats/PunishmentData.java | 39 ++++++ .../common/api/model/stats/RoleplayData.java | 42 ++++++ 11 files changed, 281 insertions(+), 55 deletions(-) delete mode 100644 src/main/java/net/turniptales/discord/common/api/API.java create mode 100644 src/main/java/net/turniptales/discord/common/api/Api.java delete mode 100644 src/main/java/net/turniptales/discord/common/api/model/Verification.java create mode 100644 src/main/java/net/turniptales/discord/common/api/model/stats/Contract.java create mode 100644 src/main/java/net/turniptales/discord/common/api/model/stats/PunishmentData.java create mode 100644 src/main/java/net/turniptales/discord/common/api/model/stats/RoleplayData.java diff --git a/src/main/java/net/turniptales/discord/Config.java b/src/main/java/net/turniptales/discord/Config.java index c4e024d..6c3a000 100644 --- a/src/main/java/net/turniptales/discord/Config.java +++ b/src/main/java/net/turniptales/discord/Config.java @@ -32,7 +32,6 @@ public class Config { public static final Role ROLE_3_YEAR = GUILD.getRoleById("1134487702864142356"); static { - assert GUILD != null; - BOT = GUILD.getMemberById("1033057310605586533"); + BOT = GUILD.getMemberById("1190714643551891478"); } } diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index 34f1f8c..3292858 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -16,6 +16,7 @@ import static java.lang.System.currentTimeMillis; import static net.dv8tion.jda.api.interactions.commands.OptionType.STRING; +import static net.dv8tion.jda.api.interactions.commands.OptionType.USER; import static net.dv8tion.jda.api.requests.GatewayIntent.GUILD_MEMBERS; import static net.dv8tion.jda.api.requests.GatewayIntent.MESSAGE_CONTENT; import static net.dv8tion.jda.api.utils.Compression.NONE; @@ -62,8 +63,8 @@ private static void startDiscordBot() { .queue(); TURNIPTALES_BOT - .upsertCommand("stats", "Statistiken eines Nutzers") - .addOption(STRING, "player", "Spielername", true) + .upsertCommand("stats", "Deine Statistiken (nicht öffentlich) oder die eines Discord Nutzers (öffentlich)") + .addOption(USER, "player", "Discord Nutzer dessen Statistiken angezeigt werden sollen (Discord Nutzer muss sich verknüpft haben)", false) .queue(); } } diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index f7873b8..4f61267 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -6,12 +6,20 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; -import net.turniptales.discord.common.api.API; +import net.turniptales.discord.common.api.Api; import net.turniptales.discord.common.api.model.PlayerStats; +import net.turniptales.discord.common.api.model.stats.PunishmentData; +import net.turniptales.discord.common.api.model.stats.RoleplayData; +import java.util.Date; +import java.util.List; +import java.util.StringJoiner; + +import static java.awt.Color.CYAN; import static java.lang.String.valueOf; import static java.util.Objects.nonNull; -import static java.util.Objects.requireNonNull; +import static net.turniptales.discord.Config.BOT; +import static net.turniptales.discord.common.api.model.stats.RoleplayData.Gender.MAN; public class StatsCommand extends ListenerAdapter { @@ -22,23 +30,107 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { } OptionMapping playerOptionMapping = e.getOption("player"); - if (!nonNull(playerOptionMapping)) { - e.reply("Gib einen Spielernamen an!").setEphemeral(true).queue(); - return; + + Api api = new Api(); + Member member = e.getMember(); + if (nonNull(playerOptionMapping)) { + PlayerStats playerStats = api.getPlayerStatsByDiscordUserId(playerOptionMapping.getAsUser().getIdLong()); + MessageEmbed publicPlayerStats = getPublicPlayerStats(playerStats, member); + e.replyEmbeds(publicPlayerStats).queue(); + } else { + PlayerStats playerStats = api.getPlayerStatsByDiscordUserId(e.getUser().getIdLong()); + MessageEmbed privatePlayerStats = getPrivatePlayerStats(playerStats, member); + e.replyEmbeds(privatePlayerStats).setEphemeral(true).queue(); } + } + + private MessageEmbed getPublicPlayerStats(PlayerStats playerStats, Member member) { + RoleplayData roleplayData = playerStats.getRoleplayData(); + + return getDefaultEmbedBuilder(playerStats, member) + .addField("Level", valueOf(playerStats.getLevel()), true) + .addField("Fraktion:", playerStats.getFaction(), true) + .addField("Kennt Spieler", valueOf(playerStats.getKnownPlayerCount()), true) - PlayerStats playerStats = API.getPlayerStats(playerOptionMapping.getAsString()); - MessageEmbed messageEmbed = createPlayerStatsMessageEmbed(playerStats, requireNonNull(e.getMember())); - e.replyEmbeds(messageEmbed).queue(); + .addField("Steckbrief", getCharacteristics(roleplayData), false) + .addBlankField(false) + .addField("Häuser:", getHouses(playerStats.getHouses()), true) + .addField("Autos:", getCars(playerStats.getCars()), true) + .build(); } - private MessageEmbed createPlayerStatsMessageEmbed(PlayerStats playerStats, Member requestor) { - return new EmbedBuilder() - .setTitle("Statistiken von " + playerStats.getMinecraftName()) - .setDescription(playerStats.getMinecraftUuid().toString()) - .addField("Online", playerStats.isOnline() ? "Ja" : "Nein", true) + private MessageEmbed getPrivatePlayerStats(PlayerStats playerStats, Member member) { + RoleplayData roleplayData = playerStats.getRoleplayData(); + + return getDefaultEmbedBuilder(playerStats, member) .addField("Level", valueOf(playerStats.getLevel()), true) - .setFooter("Angefordert von " + requestor.getUser().getAsMention(), requestor.getAvatarUrl()) + .addField("Fraktion:", playerStats.getFaction(), true) + .addField("Kennt Spieler", valueOf(playerStats.getKnownPlayerCount()), true) + + .addField("Steckbrief", getCharacteristics(roleplayData), false) + .addField("Finanzen", getBalances(roleplayData), true) + .addField("Bestrafung", getPunishments(playerStats.getPunishmentData()), true) + .addBlankField(false) + .addField("Häuser:", getHouses(playerStats.getHouses()), true) + .addField("Autos:", getCars(playerStats.getCars()), true) .build(); } + + private EmbedBuilder getDefaultEmbedBuilder(PlayerStats playerStats, Member member) { + assert BOT != null; + return new EmbedBuilder() + .setColor(CYAN) + .setThumbnail("https://minotar.net/helm/" + playerStats.getMinecraftUuid() + "/300.png") + .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setTitle("Statistiken von " + playerStats.getMinecraftName()) + .setDescription("**Role**: " + playerStats.getRole()) + .setFooter(member.getEffectiveName(), member.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + } + + private String getCharacteristics(RoleplayData roleplayData) { + return """ + **Name**: %s + **Alter**: %s + **Geschlecht**: %s + """ + .formatted(roleplayData.getFirstname() + " " + roleplayData.getLastname(), + "20", + roleplayData.getGender().equals(MAN) ? ":male_sign:" : ":female_sign:"); + } + + private String getBalances(RoleplayData roleplayData) { + return """ + **Bank**: %s$ + **Bargeld**: %s$ + **PayPal**: %s$ + """ + .formatted(roleplayData.getBankBalance(), roleplayData.getCashBalance(), roleplayData.getPayPalBalance()); + } + + private String getPunishments(PunishmentData punishmentData) { + return """ + **Waffensperre**: %s + **Fraktionssperre**: %s + **Skill-Sperre**: %s + **Ad-Sperre**: %s + **Auto-Sperre**: %s + **Checkpoints**: %s + """ + .formatted(punishmentData.isWeaponBlockActive(), punishmentData.isFactionBlockActive(), punishmentData.isSkillBlockActive(), punishmentData.isAdBlockActive(), punishmentData.isCarBlockActive(), punishmentData.getCheckpointsLeft()); + } + + private String getHouses(List houses) { + StringJoiner houseJoiner = new StringJoiner("\n- ", "- ", ""); + houses.stream() + .map(Object::toString) + .forEach(houseJoiner::add); + return !houses.isEmpty() ? houseJoiner.toString() : "keine Häuser im Besitz oder zur Miete"; + } + + private String getCars(List cars) { + StringJoiner carJoiner = new StringJoiner("\n- ", "- ", ""); + cars.forEach(carJoiner::add); + return !cars.isEmpty() ? carJoiner.toString() : "keine Autos im Besitz"; + } } diff --git a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java index 8bee8dc..721dce3 100644 --- a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java @@ -3,12 +3,11 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; -import net.turniptales.discord.common.api.model.Verification; +import net.turniptales.discord.common.api.Api; +import net.turniptales.discord.common.api.model.PlayerStats; import static java.util.Objects.nonNull; -import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.SECONDS; -import static net.turniptales.discord.common.api.API.getVerification; public class VerifyCommand extends ListenerAdapter { @@ -24,9 +23,15 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { return; } - Verification verification = getVerification(codeOptionMapping.getAsString(), requireNonNull(e.getMember()).getIdLong()); + PlayerStats playerStats = new Api().getPlayerStatsByDiscordUserIdVerify(e.getUser().getIdLong(), codeOptionMapping.getAsString()); + String message; + if (nonNull(playerStats)) { + message = "Du hast deinen Discord Account mit dem Minecraft Account " + playerStats.getMinecraftName() + " verknüpft!\nDiese Nachricht zerstört sich gleich von selbst..."; + } else { + message = "Dein Discord Account konnte nicht mit deinem Minecraft Account verknüpft werden."; + } - e.reply("Du hast deinen Discord Account mit dem Minecraft Account " + verification.getMinecraftName() + " verknüpft!\nDiese Nachricht zerstört sich gleich von selbst...").setEphemeral(true).queue(); + e.reply(message).setEphemeral(true).queue(); e.getHook().deleteOriginal().queueAfter(5, SECONDS); } } diff --git a/src/main/java/net/turniptales/discord/common/api/API.java b/src/main/java/net/turniptales/discord/common/api/API.java deleted file mode 100644 index 1a0b9bf..0000000 --- a/src/main/java/net/turniptales/discord/common/api/API.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.turniptales.discord.common.api; - -import net.turniptales.discord.common.api.model.PlayerStats; -import net.turniptales.discord.common.api.model.Verification; - -import static java.util.UUID.fromString; - -public class API { - - public static Verification getVerification(String verificationCode, long memberId) { - // rettichlp.de:8090/turniptales/v1/verification/check?code=&memberId= - return new Verification(fromString("25855f4d-3874-4a7f-a6ad-e9e4f3042e19"), "RettichLP"); - } - - public static PlayerStats getPlayerStats(String playerName) { - return new PlayerStats(fromString("25855f4d-3874-4a7f-a6ad-e9e4f3042e19"), "RettichLP", 20, true); - } -} diff --git a/src/main/java/net/turniptales/discord/common/api/Api.java b/src/main/java/net/turniptales/discord/common/api/Api.java new file mode 100644 index 0000000..2ec64e6 --- /dev/null +++ b/src/main/java/net/turniptales/discord/common/api/Api.java @@ -0,0 +1,47 @@ +package net.turniptales.discord.common.api; + +import com.google.gson.Gson; +import lombok.Data; +import lombok.extern.log4j.Log4j2; +import net.turniptales.discord.common.api.model.PlayerStats; +import org.springframework.web.reactive.function.client.WebClient; + +import static org.springframework.http.HttpMethod.GET; + +@Log4j2 +@Data +public class Api { + + /** + * {@link PlayerStats} + */ + public PlayerStats getPlayerStatsByDiscordUserId(long userId) { + return parseGetRequest("/" + userId, PlayerStats.class); + } + + public PlayerStats getPlayerStatsByDiscordUserIdVerify(long userId, String discordCode) { + return parseGetRequest("/" + userId + "?discordCode=" + discordCode, PlayerStats.class); + } + + /** + * Request + */ + private T parseGetRequest(String url, Class model) { + Gson gson = new Gson(); + return gson.fromJson(sendGetRequest(url), model); + } + + private String sendGetRequest(String url) { + return getClient(url).method(GET) + .retrieve() + .bodyToMono(String.class) + .block(); + } + + private WebClient getClient(String url) { + return WebClient.builder() + .baseUrl("https://rettichlp.de:7100/turniptalesapi/v1/discord" + url) + .defaultHeader("Authorization", "Basic dHVybmlwdGFsZXMtYXBpdXNlcjoqYnp0OThjV3EvLCckOT41SEN7NlEtTycralZFZmprMQ==") + .build(); + } +} diff --git a/src/main/java/net/turniptales/discord/common/api/model/PlayerStats.java b/src/main/java/net/turniptales/discord/common/api/model/PlayerStats.java index 5c5414e..39c5ac2 100644 --- a/src/main/java/net/turniptales/discord/common/api/model/PlayerStats.java +++ b/src/main/java/net/turniptales/discord/common/api/model/PlayerStats.java @@ -2,7 +2,11 @@ import lombok.AllArgsConstructor; import lombok.Data; +import net.turniptales.discord.common.api.model.stats.Contract; +import net.turniptales.discord.common.api.model.stats.PunishmentData; +import net.turniptales.discord.common.api.model.stats.RoleplayData; +import java.util.List; import java.util.UUID; @Data @@ -11,6 +15,14 @@ public class PlayerStats { private UUID minecraftUuid; private String minecraftName; + private String faction; private int level; private boolean online; + private PunishmentData punishmentData; + private RoleplayData roleplayData; + private List houses; + private List contracts; + private String role; + private int knownPlayerCount; + private List cars; } diff --git a/src/main/java/net/turniptales/discord/common/api/model/Verification.java b/src/main/java/net/turniptales/discord/common/api/model/Verification.java deleted file mode 100644 index 4e051a0..0000000 --- a/src/main/java/net/turniptales/discord/common/api/model/Verification.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.turniptales.discord.common.api.model; - -import lombok.AllArgsConstructor; -import lombok.Data; - -import java.util.UUID; - -@Data -@AllArgsConstructor -public class Verification { - - private UUID minecraftUuid; - private String minecraftName; -} diff --git a/src/main/java/net/turniptales/discord/common/api/model/stats/Contract.java b/src/main/java/net/turniptales/discord/common/api/model/stats/Contract.java new file mode 100644 index 0000000..280215d --- /dev/null +++ b/src/main/java/net/turniptales/discord/common/api/model/stats/Contract.java @@ -0,0 +1,21 @@ +package net.turniptales.discord.common.api.model.stats; + +import lombok.Data; + +import java.util.UUID; + +@Data +public class Contract { + + private long id; + private long startDate; + private long endDate; + private UUID owner; + private UUID partner; + private long payDayBalance; // is paid every pay day by partner + private long oneTimeBalance; // is paid at endDate by partner + + public boolean isPayedEveryPayDay(UUID minecraftUuid) { + return this.partner.equals(minecraftUuid) && this.payDayBalance > 0; + } +} diff --git a/src/main/java/net/turniptales/discord/common/api/model/stats/PunishmentData.java b/src/main/java/net/turniptales/discord/common/api/model/stats/PunishmentData.java new file mode 100644 index 0000000..a716c71 --- /dev/null +++ b/src/main/java/net/turniptales/discord/common/api/model/stats/PunishmentData.java @@ -0,0 +1,39 @@ +package net.turniptales.discord.common.api.model.stats; + +import lombok.Data; + +import java.util.Date; +import java.util.List; + +@Data +public class PunishmentData { + + private long id; + private long weaponBlockUntil; + private long factionBlockUntil; + private long skillBlockUntil; + private long adBlockUntil; + private long carBlockUntil; + private int checkpointsLeft; + private List log; + + public boolean isWeaponBlockActive() { + return new Date(this.weaponBlockUntil).after(new Date()); + } + + public boolean isFactionBlockActive() { + return new Date(this.factionBlockUntil).after(new Date()); + } + + public boolean isSkillBlockActive() { + return new Date(this.skillBlockUntil).after(new Date()); + } + + public boolean isAdBlockActive() { + return new Date(this.adBlockUntil).after(new Date()); + } + + public boolean isCarBlockActive() { + return new Date(this.carBlockUntil).after(new Date()); + } +} diff --git a/src/main/java/net/turniptales/discord/common/api/model/stats/RoleplayData.java b/src/main/java/net/turniptales/discord/common/api/model/stats/RoleplayData.java new file mode 100644 index 0000000..a287bca --- /dev/null +++ b/src/main/java/net/turniptales/discord/common/api/model/stats/RoleplayData.java @@ -0,0 +1,42 @@ +package net.turniptales.discord.common.api.model.stats; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; + +@Data +public class RoleplayData { + + private long id; + private String firstname; + private String lastname; + private Gender gender; + private long birthday; + private double bankBalance; + private double cashBalance; + private double payPalBalance; + private double wantedPercentage; + private double hydration; + + public String getRoleplayDisplayName() { + return this.firstname + " " + this.lastname; + } + + @Getter + @AllArgsConstructor + public enum Gender { + + MAN("Männlich", "Herr", "Vater", "Sohn", "Bruder"), + FEMALE("Weiblich", "Frau", "Mutter", "Tochter", "Schwester"); + + private final String adjective; + private final String salutation; + private final String parent; + private final String children; + private final String sibling; + + public String getUnknownName() { + return this.equals(MAN) ? "Fremder" : "Fremde"; + } + } +} From 8975ed9fcbbe2c0cb0a5550a17a1f1f03a042944 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Sun, 21 Jan 2024 18:10:13 +0100 Subject: [PATCH 10/58] Add logic to show private player stats in ticket channels --- .../net/turniptales/discord/commands/StatsCommand.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index 4f61267..76a1e42 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -3,6 +3,8 @@ import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.channel.Channel; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; @@ -35,7 +37,7 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { Member member = e.getMember(); if (nonNull(playerOptionMapping)) { PlayerStats playerStats = api.getPlayerStatsByDiscordUserId(playerOptionMapping.getAsUser().getIdLong()); - MessageEmbed publicPlayerStats = getPublicPlayerStats(playerStats, member); + MessageEmbed publicPlayerStats = isTicketChannel(e.getChannel()) ? getPrivatePlayerStats(playerStats, member) : getPublicPlayerStats(playerStats, member); e.replyEmbeds(publicPlayerStats).queue(); } else { PlayerStats playerStats = api.getPlayerStatsByDiscordUserId(e.getUser().getIdLong()); @@ -44,6 +46,12 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { } } + private boolean isTicketChannel(Channel channel) { + return channel instanceof TextChannel textChannel + && nonNull(textChannel.getTopic()) + && textChannel.getTopic().contains("Ticket von "); + } + private MessageEmbed getPublicPlayerStats(PlayerStats playerStats, Member member) { RoleplayData roleplayData = playerStats.getRoleplayData(); From 0766ec466ae17b5d2245e7b3fa640c429a3cf688 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Sun, 21 Jan 2024 19:22:30 +0100 Subject: [PATCH 11/58] Fix wrong api url --- .../discord/commands/StatsCommand.java | 23 ++++++++++++++----- .../turniptales/discord/common/api/Api.java | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index 76a1e42..360b703 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -20,6 +20,7 @@ import static java.awt.Color.CYAN; import static java.lang.String.valueOf; import static java.util.Objects.nonNull; +import static java.util.concurrent.TimeUnit.SECONDS; import static net.turniptales.discord.Config.BOT; import static net.turniptales.discord.common.api.model.stats.RoleplayData.Gender.MAN; @@ -36,13 +37,23 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { Api api = new Api(); Member member = e.getMember(); if (nonNull(playerOptionMapping)) { - PlayerStats playerStats = api.getPlayerStatsByDiscordUserId(playerOptionMapping.getAsUser().getIdLong()); - MessageEmbed publicPlayerStats = isTicketChannel(e.getChannel()) ? getPrivatePlayerStats(playerStats, member) : getPublicPlayerStats(playerStats, member); - e.replyEmbeds(publicPlayerStats).queue(); + try { + PlayerStats playerStats = api.getPlayerStatsByDiscordUserId(playerOptionMapping.getAsUser().getIdLong()); + MessageEmbed publicPlayerStats = isTicketChannel(e.getChannel()) ? getPrivatePlayerStats(playerStats, member) : getPublicPlayerStats(playerStats, member); + e.replyEmbeds(publicPlayerStats).queue(); + } catch (Exception ex) { + e.reply("Der angegebene Spieler hat seinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); + e.getHook().deleteOriginal().queueAfter(5, SECONDS); + } } else { - PlayerStats playerStats = api.getPlayerStatsByDiscordUserId(e.getUser().getIdLong()); - MessageEmbed privatePlayerStats = getPrivatePlayerStats(playerStats, member); - e.replyEmbeds(privatePlayerStats).setEphemeral(true).queue(); + try { + PlayerStats playerStats = api.getPlayerStatsByDiscordUserId(e.getUser().getIdLong()); + MessageEmbed privatePlayerStats = getPrivatePlayerStats(playerStats, member); + e.replyEmbeds(privatePlayerStats).setEphemeral(true).queue(); + } catch (Exception ex) { + e.reply("Du hast deinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); + e.getHook().deleteOriginal().queueAfter(5, SECONDS); + } } } diff --git a/src/main/java/net/turniptales/discord/common/api/Api.java b/src/main/java/net/turniptales/discord/common/api/Api.java index 2ec64e6..ecd5748 100644 --- a/src/main/java/net/turniptales/discord/common/api/Api.java +++ b/src/main/java/net/turniptales/discord/common/api/Api.java @@ -40,7 +40,7 @@ private String sendGetRequest(String url) { private WebClient getClient(String url) { return WebClient.builder() - .baseUrl("https://rettichlp.de:7100/turniptalesapi/v1/discord" + url) + .baseUrl("https://rettichlp.de:7100/turniptalesapi/v1/verification/discord" + url) .defaultHeader("Authorization", "Basic dHVybmlwdGFsZXMtYXBpdXNlcjoqYnp0OThjV3EvLCckOT41SEN7NlEtTycralZFZmprMQ==") .build(); } From f0ad3f64ef41a7fb688f67a44c21369135a4f82e Mon Sep 17 00:00:00 2001 From: rettichlp Date: Sun, 21 Jan 2024 19:37:28 +0100 Subject: [PATCH 12/58] Code clean up --- .../java/net/turniptales/discord/commands/VerifyCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java index 721dce3..96202b4 100644 --- a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java @@ -6,6 +6,7 @@ import net.turniptales.discord.common.api.Api; import net.turniptales.discord.common.api.model.PlayerStats; +import static java.util.Objects.isNull; import static java.util.Objects.nonNull; import static java.util.concurrent.TimeUnit.SECONDS; @@ -18,7 +19,7 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { } OptionMapping codeOptionMapping = e.getOption("code"); - if (!nonNull(codeOptionMapping)) { + if (isNull(codeOptionMapping)) { e.reply("Gib einen Verifizierungscode an!").setEphemeral(true).queue(); return; } From 86369bea470f2db83ca8ebdc854feed1b690b6d1 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Tue, 30 Jan 2024 01:54:52 +0100 Subject: [PATCH 13/58] Update join and leave messages --- .../java/net/turniptales/discord/Config.java | 2 +- .../discord/TurnipTalesDiscord.java | 22 ++++--- .../discord/events/GuildBanEventHandler.java | 34 ---------- .../events/GuildMemberJoinEventHandler.java | 38 ----------- .../events/GuildMemberJoinListener.java | 39 +++++++++++ .../events/GuildMemberRemoveEventHandler.java | 35 ---------- .../events/GuildMemberRemoveListener.java | 64 +++++++++++++++++++ .../GuildMemberUpdateBoostTimeListener.java | 36 +++++++++++ 8 files changed, 154 insertions(+), 116 deletions(-) delete mode 100644 src/main/java/net/turniptales/discord/events/GuildBanEventHandler.java delete mode 100644 src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java create mode 100644 src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java delete mode 100644 src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java create mode 100644 src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java create mode 100644 src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java diff --git a/src/main/java/net/turniptales/discord/Config.java b/src/main/java/net/turniptales/discord/Config.java index 6c3a000..1de21ee 100644 --- a/src/main/java/net/turniptales/discord/Config.java +++ b/src/main/java/net/turniptales/discord/Config.java @@ -13,8 +13,8 @@ public class Config { public static final Guild GUILD = TURNIPTALES_BOT.getGuildById("1008928645185810463"); public static final Member BOT; // channels - public static final TextChannel SYSTEM_TEXT_CHANNEL = GUILD.getSystemChannel(); public static final TextChannel TICKET_TEXT_CHANNEL = GUILD.getTextChannelById("1009477703990267954"); + public static final TextChannel MISSION_CONTROL_TEXT_CHANNEL = GUILD.getTextChannelById("1201654273923100772"); // public static final Category TICKET_CATEGORY = GUILD.getCategoryById("1009478372847517727"); // team roles diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index 3292858..da1bcc9 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -6,9 +6,9 @@ import net.turniptales.discord.commands.StatsCommand; import net.turniptales.discord.commands.TicketCommand; import net.turniptales.discord.commands.VerifyCommand; -import net.turniptales.discord.events.GuildBanEventHandler; -import net.turniptales.discord.events.GuildMemberJoinEventHandler; -import net.turniptales.discord.events.GuildMemberRemoveEventHandler; +import net.turniptales.discord.events.GuildMemberJoinListener; +import net.turniptales.discord.events.GuildMemberRemoveListener; +import net.turniptales.discord.events.GuildMemberUpdateBoostTimeListener; import net.turniptales.discord.events.TicketEventHandler; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -46,11 +46,17 @@ private static void startDiscordBot() { .setCompression(NONE) // Disable compression (not recommended) .enableIntents(MESSAGE_CONTENT) .enableIntents(GUILD_MEMBERS) - .addEventListeners(new TicketCommand(), new VerifyCommand(), new StatsCommand()) - .addEventListeners(new GuildMemberJoinEventHandler()) - .addEventListeners(new GuildMemberRemoveEventHandler()) - .addEventListeners(new GuildBanEventHandler()) - .addEventListeners(new TicketEventHandler()) + .addEventListeners( + new TicketCommand(), + new VerifyCommand(), + new StatsCommand() + ) + .addEventListeners( + new GuildMemberJoinListener(), + new GuildMemberRemoveListener(), + new GuildMemberUpdateBoostTimeListener(), + new TicketEventHandler() + ) .build(); TURNIPTALES_BOT diff --git a/src/main/java/net/turniptales/discord/events/GuildBanEventHandler.java b/src/main/java/net/turniptales/discord/events/GuildBanEventHandler.java deleted file mode 100644 index 7b7f6a9..0000000 --- a/src/main/java/net/turniptales/discord/events/GuildBanEventHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.turniptales.discord.events; - -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.guild.GuildBanEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import static java.awt.Color.RED; - -public class GuildBanEventHandler extends ListenerAdapter { - - @Override - public void onGuildBan(GuildBanEvent e) { - Guild guild = e.getGuild(); - TextChannel systemChannel = guild.getSystemChannel(); - if (systemChannel == null) { - return; - } - - User user = e.getUser(); - int memberCount = guild.getMemberCount(); - - EmbedBuilder embedBuilder = new EmbedBuilder() - .setColor(RED) - .setTitle(user.getAsTag()) - .setThumbnail(user.getAvatarUrl()) - .setDescription("Wurde von **" + guild.getName() + "** gebannt!"); - - systemChannel.sendMessageEmbeds(embedBuilder.build()).queue(); - systemChannel.getManager().setTopic("Aktuelle Spieler: " + memberCount).queue(); - } -} diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java b/src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java deleted file mode 100644 index 157c987..0000000 --- a/src/main/java/net/turniptales/discord/events/GuildMemberJoinEventHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package net.turniptales.discord.events; - -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import static java.awt.Color.GREEN; -import static net.turniptales.discord.Config.ROLE_0; - -public class GuildMemberJoinEventHandler extends ListenerAdapter { - - @Override - public void onGuildMemberJoin(GuildMemberJoinEvent e) { - Guild guild = e.getGuild(); - TextChannel systemChannel = guild.getSystemChannel(); - if (systemChannel == null) { - return; - } - - User user = e.getUser(); - int memberCount = guild.getMemberCount(); - - EmbedBuilder embedBuilder = new EmbedBuilder() - .setColor(GREEN) - .setTitle(user.getAsTag()) - .setThumbnail(user.getAvatarUrl()) - .setDescription("Ist **" + guild.getName() + "** beigetreten!\nHier sind nun **" + memberCount + "** Spieler."); - - systemChannel.sendMessageEmbeds(embedBuilder.build()).queue(); - systemChannel.getManager().setTopic("Aktuelle Spieler: " + memberCount).queue(); - - assert ROLE_0 != null; - guild.addRoleToMember(user, ROLE_0).queue(); - } -} diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java b/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java new file mode 100644 index 0000000..f6f660a --- /dev/null +++ b/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java @@ -0,0 +1,39 @@ +package net.turniptales.discord.events; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +import java.util.Date; + +import static java.awt.Color.CYAN; +import static java.util.Objects.nonNull; +import static net.turniptales.discord.Config.BOT; +import static net.turniptales.discord.Config.ROLE_0; + +public class GuildMemberJoinListener extends ListenerAdapter { + + @Override + public void onGuildMemberJoin(GuildMemberJoinEvent e) { + Guild guild = e.getGuild(); + TextChannel systemChannel = guild.getSystemChannel(); + if (nonNull(systemChannel) && nonNull(BOT) && nonNull(ROLE_0)) { + Member member = e.getMember(); + + EmbedBuilder embedBuilder = new EmbedBuilder() + .setColor(CYAN) + .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setTitle("Willkommen auf TurnipTales!") + .setDescription(member.getAsMention() + " hat den Server betreten.") + .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), member.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + systemChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + + guild.addRoleToMember(e.getUser(), ROLE_0).queue(); + } + } +} diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java b/src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java deleted file mode 100644 index 55da83e..0000000 --- a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveEventHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.turniptales.discord.events; - -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import static java.awt.Color.ORANGE; -import static net.turniptales.discord.Config.SYSTEM_TEXT_CHANNEL; - -public class GuildMemberRemoveEventHandler extends ListenerAdapter { - - @Override - public void onGuildMemberRemove(GuildMemberRemoveEvent e) { - Guild guild = e.getGuild(); - TextChannel systemChannel = SYSTEM_TEXT_CHANNEL; - if (systemChannel == null) { - return; - } - - User user = e.getUser(); - int memberCount = guild.getMemberCount(); - - EmbedBuilder embedBuilder = new EmbedBuilder() - .setColor(ORANGE) - .setTitle(user.getAsTag()) - .setThumbnail(user.getAvatarUrl()) - .setDescription("Hat **" + guild.getName() + "** verlassen!\nHier sind nun **" + memberCount + "** Spieler."); - - systemChannel.sendMessageEmbeds(embedBuilder.build()).queue(); - systemChannel.getManager().setTopic("Aktuelle Spieler: " + memberCount).queue(); - } -} diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java b/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java new file mode 100644 index 0000000..99e6e14 --- /dev/null +++ b/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java @@ -0,0 +1,64 @@ +package net.turniptales.discord.events; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.guild.GuildBanEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +import java.awt.Color; +import java.util.Date; + +import static java.util.Objects.nonNull; +import static net.turniptales.discord.Config.BOT; +import static net.turniptales.discord.Config.MISSION_CONTROL_TEXT_CHANNEL; + +public class GuildMemberRemoveListener extends ListenerAdapter { + + @Override + public void onGuildMemberRemove(GuildMemberRemoveEvent e) { + Guild guild = e.getGuild(); + User user = e.getUser(); + TextChannel missionControlTextChannel = MISSION_CONTROL_TEXT_CHANNEL; + if (nonNull(missionControlTextChannel) && nonNull(BOT)) { + EmbedBuilder embedBuilder = new EmbedBuilder() + .setColor(new Color(85, 85, 85)) + .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setDescription(user.getAsMention() + " hat den Server verlassen.") + .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), user.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + missionControlTextChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onGuildBan(GuildBanEvent e) { + Guild guild = e.getGuild(); + User user = e.getUser(); + TextChannel systemChannel = guild.getSystemChannel(); + TextChannel missionControlTextChannel = MISSION_CONTROL_TEXT_CHANNEL; + if (nonNull(systemChannel) && nonNull(missionControlTextChannel) && nonNull(BOT)) { + Color color = new Color(255, 85, 85); + EmbedBuilder embedBuilderSystemChannel = new EmbedBuilder() + .setColor(color) + .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setTitle("Auf wiedersehen!") + .setDescription(user.getAsMention() + " nimmt sich eine Auszeit.") + .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), user.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + EmbedBuilder embedBuilderMissionControlTextChannel = new EmbedBuilder() + .setColor(color) + .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setDescription(user.getAsMention() + " wurde gebannt.") + .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), user.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + systemChannel.sendMessageEmbeds(embedBuilderSystemChannel.build()).queue(); + missionControlTextChannel.sendMessageEmbeds(embedBuilderMissionControlTextChannel.build()).queue(); + } + } +} diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java b/src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java new file mode 100644 index 0000000..d21d241 --- /dev/null +++ b/src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java @@ -0,0 +1,36 @@ +package net.turniptales.discord.events; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateBoostTimeEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +import java.awt.Color; +import java.util.Date; + +import static java.util.Objects.nonNull; +import static net.turniptales.discord.Config.BOT; + +public class GuildMemberUpdateBoostTimeListener extends ListenerAdapter { + + @Override + public void onGuildMemberUpdateBoostTime(GuildMemberUpdateBoostTimeEvent e) { + Guild guild = e.getGuild(); + TextChannel systemChannel = guild.getSystemChannel(); + if (nonNull(systemChannel) && nonNull(BOT)) { + Member member = e.getMember(); + + EmbedBuilder embedBuilder = new EmbedBuilder() + .setColor(new Color(85, 255, 255)) + .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setTitle("Danke für den Boost!") + .setDescription(member.getAsMention() + " hat den Server geboostet.") + .setFooter("Aktuelle Boosts: **" + guild.getBoostCount() + "** (" + guild.getBoostTier() + ")", member.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + systemChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } +} From 993c186bbe5b284c24fb07981b845c78a0def9bc Mon Sep 17 00:00:00 2001 From: rettichlp Date: Wed, 31 Jan 2024 01:40:00 +0100 Subject: [PATCH 14/58] Fix channel selection --- .../java/net/turniptales/discord/Config.java | 2 +- .../events/GuildMemberJoinListener.java | 18 +++++++++++++---- .../events/GuildMemberRemoveListener.java | 20 +++++++++---------- .../GuildMemberUpdateBoostTimeListener.java | 7 ++++--- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/main/java/net/turniptales/discord/Config.java b/src/main/java/net/turniptales/discord/Config.java index 1de21ee..a18d4da 100644 --- a/src/main/java/net/turniptales/discord/Config.java +++ b/src/main/java/net/turniptales/discord/Config.java @@ -14,7 +14,7 @@ public class Config { public static final Member BOT; // channels public static final TextChannel TICKET_TEXT_CHANNEL = GUILD.getTextChannelById("1009477703990267954"); - public static final TextChannel MISSION_CONTROL_TEXT_CHANNEL = GUILD.getTextChannelById("1201654273923100772"); + public static final TextChannel COMMUNITY_TEXT_CHANNEL = GUILD.getTextChannelById("1008929885764472952"); // public static final Category TICKET_CATEGORY = GUILD.getCategoryById("1009478372847517727"); // team roles diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java b/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java index f6f660a..b56139e 100644 --- a/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java +++ b/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java @@ -12,6 +12,7 @@ import static java.awt.Color.CYAN; import static java.util.Objects.nonNull; import static net.turniptales.discord.Config.BOT; +import static net.turniptales.discord.Config.COMMUNITY_TEXT_CHANNEL; import static net.turniptales.discord.Config.ROLE_0; public class GuildMemberJoinListener extends ListenerAdapter { @@ -19,11 +20,12 @@ public class GuildMemberJoinListener extends ListenerAdapter { @Override public void onGuildMemberJoin(GuildMemberJoinEvent e) { Guild guild = e.getGuild(); - TextChannel systemChannel = guild.getSystemChannel(); - if (nonNull(systemChannel) && nonNull(BOT) && nonNull(ROLE_0)) { + TextChannel communityTextChannel = COMMUNITY_TEXT_CHANNEL; + TextChannel missionControlTextChannel = guild.getSystemChannel(); + if (nonNull(communityTextChannel) && nonNull(missionControlTextChannel) && nonNull(BOT) && nonNull(ROLE_0)) { Member member = e.getMember(); - EmbedBuilder embedBuilder = new EmbedBuilder() + EmbedBuilder embedBuildercommunityTextChannel = new EmbedBuilder() .setColor(CYAN) .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) .setTitle("Willkommen auf TurnipTales!") @@ -31,7 +33,15 @@ public void onGuildMemberJoin(GuildMemberJoinEvent e) { .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), member.getEffectiveAvatarUrl()) .setTimestamp(new Date().toInstant()); - systemChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + EmbedBuilder embedBuildermissionControlTextChannel = new EmbedBuilder() + .setColor(CYAN) + .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setDescription(member.getAsMention() + " hat den Server betreten.") + .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), member.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + communityTextChannel.sendMessageEmbeds(embedBuildercommunityTextChannel.build()).queue(); + missionControlTextChannel.sendMessageEmbeds(embedBuildermissionControlTextChannel.build()).queue(); guild.addRoleToMember(e.getUser(), ROLE_0).queue(); } diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java b/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java index 99e6e14..55436dd 100644 --- a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java +++ b/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java @@ -13,7 +13,7 @@ import static java.util.Objects.nonNull; import static net.turniptales.discord.Config.BOT; -import static net.turniptales.discord.Config.MISSION_CONTROL_TEXT_CHANNEL; +import static net.turniptales.discord.Config.COMMUNITY_TEXT_CHANNEL; public class GuildMemberRemoveListener extends ListenerAdapter { @@ -21,7 +21,7 @@ public class GuildMemberRemoveListener extends ListenerAdapter { public void onGuildMemberRemove(GuildMemberRemoveEvent e) { Guild guild = e.getGuild(); User user = e.getUser(); - TextChannel missionControlTextChannel = MISSION_CONTROL_TEXT_CHANNEL; + TextChannel missionControlTextChannel = guild.getSystemChannel(); if (nonNull(missionControlTextChannel) && nonNull(BOT)) { EmbedBuilder embedBuilder = new EmbedBuilder() .setColor(new Color(85, 85, 85)) @@ -37,12 +37,12 @@ public void onGuildMemberRemove(GuildMemberRemoveEvent e) { @Override public void onGuildBan(GuildBanEvent e) { Guild guild = e.getGuild(); - User user = e.getUser(); - TextChannel systemChannel = guild.getSystemChannel(); - TextChannel missionControlTextChannel = MISSION_CONTROL_TEXT_CHANNEL; - if (nonNull(systemChannel) && nonNull(missionControlTextChannel) && nonNull(BOT)) { + TextChannel communityTextChannel = COMMUNITY_TEXT_CHANNEL; + TextChannel missionControlTextChannel = guild.getSystemChannel(); + if (nonNull(communityTextChannel) && nonNull(missionControlTextChannel) && nonNull(BOT)) { + User user = e.getUser(); Color color = new Color(255, 85, 85); - EmbedBuilder embedBuilderSystemChannel = new EmbedBuilder() + EmbedBuilder embedBuildercommunityTextChannel = new EmbedBuilder() .setColor(color) .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) .setTitle("Auf wiedersehen!") @@ -50,15 +50,15 @@ public void onGuildBan(GuildBanEvent e) { .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), user.getEffectiveAvatarUrl()) .setTimestamp(new Date().toInstant()); - EmbedBuilder embedBuilderMissionControlTextChannel = new EmbedBuilder() + EmbedBuilder embedBuildermissionControlTextChannel = new EmbedBuilder() .setColor(color) .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) .setDescription(user.getAsMention() + " wurde gebannt.") .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), user.getEffectiveAvatarUrl()) .setTimestamp(new Date().toInstant()); - systemChannel.sendMessageEmbeds(embedBuilderSystemChannel.build()).queue(); - missionControlTextChannel.sendMessageEmbeds(embedBuilderMissionControlTextChannel.build()).queue(); + communityTextChannel.sendMessageEmbeds(embedBuildercommunityTextChannel.build()).queue(); + missionControlTextChannel.sendMessageEmbeds(embedBuildermissionControlTextChannel.build()).queue(); } } } diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java b/src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java index d21d241..4f639b7 100644 --- a/src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java +++ b/src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java @@ -12,14 +12,15 @@ import static java.util.Objects.nonNull; import static net.turniptales.discord.Config.BOT; +import static net.turniptales.discord.Config.COMMUNITY_TEXT_CHANNEL; public class GuildMemberUpdateBoostTimeListener extends ListenerAdapter { @Override public void onGuildMemberUpdateBoostTime(GuildMemberUpdateBoostTimeEvent e) { Guild guild = e.getGuild(); - TextChannel systemChannel = guild.getSystemChannel(); - if (nonNull(systemChannel) && nonNull(BOT)) { + TextChannel communityTextChannel = COMMUNITY_TEXT_CHANNEL; + if (nonNull(communityTextChannel) && nonNull(BOT)) { Member member = e.getMember(); EmbedBuilder embedBuilder = new EmbedBuilder() @@ -30,7 +31,7 @@ public void onGuildMemberUpdateBoostTime(GuildMemberUpdateBoostTimeEvent e) { .setFooter("Aktuelle Boosts: **" + guild.getBoostCount() + "** (" + guild.getBoostTier() + ")", member.getEffectiveAvatarUrl()) .setTimestamp(new Date().toInstant()); - systemChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + communityTextChannel.sendMessageEmbeds(embedBuilder.build()).queue(); } } } From d314cb63e98a9fe6fa5a17de8db69148b0c96652 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Fri, 9 Feb 2024 15:41:23 +0100 Subject: [PATCH 15/58] Reformat code --- .../discord/commands/StatsCommand.java | 2 +- .../events/GuildMemberRemoveListener.java | 34 +++++----- .../discord/events/TicketEventHandler.java | 66 +++++++++---------- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index 360b703..9ce611b 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -113,7 +113,7 @@ private String getCharacteristics(RoleplayData roleplayData) { **Alter**: %s **Geschlecht**: %s """ - .formatted(roleplayData.getFirstname() + " " + roleplayData.getLastname(), + .formatted(roleplayData.getFirstname() + " " + roleplayData.getLastname(), "20", roleplayData.getGender().equals(MAN) ? ":male_sign:" : ":female_sign:"); } diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java b/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java index 55436dd..0835e6b 100644 --- a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java +++ b/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java @@ -17,23 +17,6 @@ public class GuildMemberRemoveListener extends ListenerAdapter { - @Override - public void onGuildMemberRemove(GuildMemberRemoveEvent e) { - Guild guild = e.getGuild(); - User user = e.getUser(); - TextChannel missionControlTextChannel = guild.getSystemChannel(); - if (nonNull(missionControlTextChannel) && nonNull(BOT)) { - EmbedBuilder embedBuilder = new EmbedBuilder() - .setColor(new Color(85, 85, 85)) - .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) - .setDescription(user.getAsMention() + " hat den Server verlassen.") - .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), user.getEffectiveAvatarUrl()) - .setTimestamp(new Date().toInstant()); - - missionControlTextChannel.sendMessageEmbeds(embedBuilder.build()).queue(); - } - } - @Override public void onGuildBan(GuildBanEvent e) { Guild guild = e.getGuild(); @@ -61,4 +44,21 @@ public void onGuildBan(GuildBanEvent e) { missionControlTextChannel.sendMessageEmbeds(embedBuildermissionControlTextChannel.build()).queue(); } } + + @Override + public void onGuildMemberRemove(GuildMemberRemoveEvent e) { + Guild guild = e.getGuild(); + User user = e.getUser(); + TextChannel missionControlTextChannel = guild.getSystemChannel(); + if (nonNull(missionControlTextChannel) && nonNull(BOT)) { + EmbedBuilder embedBuilder = new EmbedBuilder() + .setColor(new Color(85, 85, 85)) + .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setDescription(user.getAsMention() + " hat den Server verlassen.") + .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), user.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + missionControlTextChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } } diff --git a/src/main/java/net/turniptales/discord/events/TicketEventHandler.java b/src/main/java/net/turniptales/discord/events/TicketEventHandler.java index 18526c0..bdba5b1 100644 --- a/src/main/java/net/turniptales/discord/events/TicketEventHandler.java +++ b/src/main/java/net/turniptales/discord/events/TicketEventHandler.java @@ -28,39 +28,6 @@ public class TicketEventHandler extends ListenerAdapter { - @Override - public void onModalInteraction(ModalInteractionEvent e) { - String modalId = e.getModalId(); - - switch (modalId) { - case "ticket_modal": - Member member = e.getMember(); - assert member != null; - String memberId = member.getId(); - String userName = member.getUser().getName(); - - String minecraftName = e.getValue("minecraft_name_input").getAsString(); - String log = e.getValue("topic_input").getAsString(); - - assert GUILD != null; - assert MODERATOR_ROLE != null; - assert SUPPORTER_ROLE != null; - TICKET_CATEGORY.createTextChannel("ticket-" + userName) - .setTopic("Ticket von " + userName + " (" + memberId + ")") - .addPermissionOverride(GUILD.getPublicRole(), null, EnumSet.of(VIEW_CHANNEL)) - .addPermissionOverride(member, EnumSet.of(VIEW_CHANNEL), null) - .addPermissionOverride(MODERATOR_ROLE, EnumSet.of(VIEW_CHANNEL), null) - .addPermissionOverride(SUPPORTER_ROLE, EnumSet.of(VIEW_CHANNEL), null) - .queue(textChannel -> textChannel - .sendMessage("Hey " + member.getAsMention() + "! Danke dass du ein Ticket erstellt hast. Die " + SUPPORTER_ROLE.getAsMention() + " und " + MODERATOR_ROLE.getAsMention() + " werden Dir schnellstmöglich deine Frage beantworten oder Dir helfen.\n" - + "Spieler: " + minecraftName + "\n" - + "Anliegen: " + log) - .addActionRow(success("closeTicket", "Ticket schließen").withEmoji(fromUnicode("U+1F512"))) - .queue(message -> e.reply("Du hast ein Ticket erstellt: " + message.getJumpUrl()).setEphemeral(true).queue())); - break; - } - } - @Override public void onButtonInteraction(ButtonInteractionEvent e) { String componentId = e.getComponentId(); @@ -121,4 +88,37 @@ public void onButtonInteraction(ButtonInteractionEvent e) { case "closeTicketAbort" -> e.getMessage().delete().queue(); } } + + @Override + public void onModalInteraction(ModalInteractionEvent e) { + String modalId = e.getModalId(); + + switch (modalId) { + case "ticket_modal": + Member member = e.getMember(); + assert member != null; + String memberId = member.getId(); + String userName = member.getUser().getName(); + + String minecraftName = e.getValue("minecraft_name_input").getAsString(); + String log = e.getValue("topic_input").getAsString(); + + assert GUILD != null; + assert MODERATOR_ROLE != null; + assert SUPPORTER_ROLE != null; + TICKET_CATEGORY.createTextChannel("ticket-" + userName) + .setTopic("Ticket von " + userName + " (" + memberId + ")") + .addPermissionOverride(GUILD.getPublicRole(), null, EnumSet.of(VIEW_CHANNEL)) + .addPermissionOverride(member, EnumSet.of(VIEW_CHANNEL), null) + .addPermissionOverride(MODERATOR_ROLE, EnumSet.of(VIEW_CHANNEL), null) + .addPermissionOverride(SUPPORTER_ROLE, EnumSet.of(VIEW_CHANNEL), null) + .queue(textChannel -> textChannel + .sendMessage("Hey " + member.getAsMention() + "! Danke dass du ein Ticket erstellt hast. Die " + SUPPORTER_ROLE.getAsMention() + " und " + MODERATOR_ROLE.getAsMention() + " werden Dir schnellstmöglich deine Frage beantworten oder Dir helfen.\n" + + "Spieler: " + minecraftName + "\n" + + "Anliegen: " + log) + .addActionRow(success("closeTicket", "Ticket schließen").withEmoji(fromUnicode("U+1F512"))) + .queue(message -> e.reply("Du hast ein Ticket erstellt: " + message.getJumpUrl()).setEphemeral(true).queue())); + break; + } + } } From 41ea6676c1c55d6cbc894730b9af7d53f9d6fddb Mon Sep 17 00:00:00 2001 From: rettichlp Date: Sun, 11 Feb 2024 22:48:04 +0100 Subject: [PATCH 16/58] Add player role handling --- src/main/java/net/turniptales/discord/Config.java | 2 ++ .../turniptales/discord/common/services/RoleSyncService.java | 5 ++++- .../turniptales/discord/events/GuildMemberJoinListener.java | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/turniptales/discord/Config.java b/src/main/java/net/turniptales/discord/Config.java index a18d4da..5a4a1ad 100644 --- a/src/main/java/net/turniptales/discord/Config.java +++ b/src/main/java/net/turniptales/discord/Config.java @@ -17,6 +17,8 @@ public class Config { public static final TextChannel COMMUNITY_TEXT_CHANNEL = GUILD.getTextChannelById("1008929885764472952"); // public static final Category TICKET_CATEGORY = GUILD.getCategoryById("1009478372847517727"); + // player roles + public static final Role PLAYER_ROLE = GUILD.getRoleById("1190675464549847110"); // team roles public static final Role MODERATOR_ROLE = GUILD.getRoleById("1025864289346658355"); public static final Role SUPPORTER_ROLE = GUILD.getRoleById("1009477020427747408"); diff --git a/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java b/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java index 4cdee41..96da542 100644 --- a/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java +++ b/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java @@ -14,6 +14,7 @@ import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.HOURS; import static net.turniptales.discord.Config.GUILD; +import static net.turniptales.discord.Config.PLAYER_ROLE; import static net.turniptales.discord.Config.ROLE_0; import static net.turniptales.discord.Config.ROLE_1_MONTH; import static net.turniptales.discord.Config.ROLE_1_WEEK; @@ -63,7 +64,9 @@ public void run() { log.info("Discord role synchronising: Remove role {} from member {}", role.getName(), member.getEffectiveName()); }); - if (!member.getRoles().contains(highestRoleUserShouldHave)) { + if (!member.getRoles().contains(PLAYER_ROLE) || !member.getRoles().contains(highestRoleUserShouldHave)) { + assert PLAYER_ROLE != null; + guild.addRoleToMember(member, PLAYER_ROLE).queue(); guild.addRoleToMember(member, highestRoleUserShouldHave).queue(); log.info("Discord role synchronising: Add role {} to member {}", highestRoleUserShouldHave.getName(), member.getEffectiveName()); } diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java b/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java index b56139e..22713bf 100644 --- a/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java +++ b/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java @@ -13,6 +13,7 @@ import static java.util.Objects.nonNull; import static net.turniptales.discord.Config.BOT; import static net.turniptales.discord.Config.COMMUNITY_TEXT_CHANNEL; +import static net.turniptales.discord.Config.PLAYER_ROLE; import static net.turniptales.discord.Config.ROLE_0; public class GuildMemberJoinListener extends ListenerAdapter { @@ -22,7 +23,7 @@ public void onGuildMemberJoin(GuildMemberJoinEvent e) { Guild guild = e.getGuild(); TextChannel communityTextChannel = COMMUNITY_TEXT_CHANNEL; TextChannel missionControlTextChannel = guild.getSystemChannel(); - if (nonNull(communityTextChannel) && nonNull(missionControlTextChannel) && nonNull(BOT) && nonNull(ROLE_0)) { + if (nonNull(communityTextChannel) && nonNull(missionControlTextChannel) && nonNull(BOT) && nonNull(PLAYER_ROLE) && nonNull(ROLE_0)) { Member member = e.getMember(); EmbedBuilder embedBuildercommunityTextChannel = new EmbedBuilder() @@ -43,6 +44,7 @@ public void onGuildMemberJoin(GuildMemberJoinEvent e) { communityTextChannel.sendMessageEmbeds(embedBuildercommunityTextChannel.build()).queue(); missionControlTextChannel.sendMessageEmbeds(embedBuildermissionControlTextChannel.build()).queue(); + guild.addRoleToMember(e.getUser(), PLAYER_ROLE).queue(); guild.addRoleToMember(e.getUser(), ROLE_0).queue(); } } From c740170e427b450ed6d1b814b52ba44dcdfdf62a Mon Sep 17 00:00:00 2001 From: rettichlp Date: Sun, 11 Feb 2024 23:14:11 +0100 Subject: [PATCH 17/58] Add survey --- .../java/net/turniptales/discord/Config.java | 3 +- .../discord/TurnipTalesDiscord.java | 33 ++++-- .../discord/commands/SurveyCommand.java | 104 ++++++++++++++++++ ...er.java => ButtonInteractionListener.java} | 22 +++- .../events/MessageReactionListener.java | 22 ++++ 5 files changed, 173 insertions(+), 11 deletions(-) create mode 100644 src/main/java/net/turniptales/discord/commands/SurveyCommand.java rename src/main/java/net/turniptales/discord/events/{TicketEventHandler.java => ButtonInteractionListener.java} (84%) create mode 100644 src/main/java/net/turniptales/discord/events/MessageReactionListener.java diff --git a/src/main/java/net/turniptales/discord/Config.java b/src/main/java/net/turniptales/discord/Config.java index 5a4a1ad..fa16986 100644 --- a/src/main/java/net/turniptales/discord/Config.java +++ b/src/main/java/net/turniptales/discord/Config.java @@ -13,8 +13,9 @@ public class Config { public static final Guild GUILD = TURNIPTALES_BOT.getGuildById("1008928645185810463"); public static final Member BOT; // channels - public static final TextChannel TICKET_TEXT_CHANNEL = GUILD.getTextChannelById("1009477703990267954"); public static final TextChannel COMMUNITY_TEXT_CHANNEL = GUILD.getTextChannelById("1008929885764472952"); + public static final TextChannel SURVEY_TEXT_CHANNEL = GUILD.getTextChannelById("1206336710128959519"); + public static final TextChannel TICKET_TEXT_CHANNEL = GUILD.getTextChannelById("1009477703990267954"); // public static final Category TICKET_CATEGORY = GUILD.getCategoryById("1009478372847517727"); // player roles diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index da1bcc9..6d83b32 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -4,12 +4,14 @@ import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; import net.turniptales.discord.commands.StatsCommand; +import net.turniptales.discord.commands.SurveyCommand; import net.turniptales.discord.commands.TicketCommand; import net.turniptales.discord.commands.VerifyCommand; +import net.turniptales.discord.events.ButtonInteractionListener; import net.turniptales.discord.events.GuildMemberJoinListener; import net.turniptales.discord.events.GuildMemberRemoveListener; import net.turniptales.discord.events.GuildMemberUpdateBoostTimeListener; -import net.turniptales.discord.events.TicketEventHandler; +import net.turniptales.discord.events.MessageReactionListener; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -47,30 +49,43 @@ private static void startDiscordBot() { .enableIntents(MESSAGE_CONTENT) .enableIntents(GUILD_MEMBERS) .addEventListeners( + new StatsCommand(), + new SurveyCommand(), new TicketCommand(), - new VerifyCommand(), - new StatsCommand() + new VerifyCommand() ) .addEventListeners( + new ButtonInteractionListener(), new GuildMemberJoinListener(), new GuildMemberRemoveListener(), new GuildMemberUpdateBoostTimeListener(), - new TicketEventHandler() + new MessageReactionListener() ) .build(); TURNIPTALES_BOT - .upsertCommand("ticket", "Erstellt die Nachricht um Tickets zu erstellen") + .upsertCommand("stats", "Deine Statistiken (nicht öffentlich) oder die eines Discord Nutzers (öffentlich)") + .addOption(USER, "player", "Discord Nutzer dessen Statistiken angezeigt werden sollen (Discord Nutzer muss sich verknüpft haben)", false) .queue(); TURNIPTALES_BOT - .upsertCommand("verify", "Verifiziert deinen Minecraft Account") - .addOption(STRING, "code", "Verifizierungscode", true) + .upsertCommand("umfrage", "Erstellt eine Umfrage") + .addOption(STRING, "question", "Frage", true) + .addOption(STRING, "description", "Beschreibung", true) + .addOption(STRING, "answer1", "Antwort 1", true) + .addOption(STRING, "answer2", "Antwort 2", true) + .addOption(STRING, "answer3", "Antwort 3", false) + .addOption(STRING, "answer4", "Antwort 4", false) + .addOption(STRING, "answer5", "Antwort 5", false) .queue(); TURNIPTALES_BOT - .upsertCommand("stats", "Deine Statistiken (nicht öffentlich) oder die eines Discord Nutzers (öffentlich)") - .addOption(USER, "player", "Discord Nutzer dessen Statistiken angezeigt werden sollen (Discord Nutzer muss sich verknüpft haben)", false) + .upsertCommand("ticket", "Erstellt die Nachricht um Tickets zu erstellen") + .queue(); + + TURNIPTALES_BOT + .upsertCommand("verify", "Verifiziert deinen Minecraft Account") + .addOption(STRING, "code", "Verifizierungscode", true) .queue(); } } diff --git a/src/main/java/net/turniptales/discord/commands/SurveyCommand.java b/src/main/java/net/turniptales/discord/commands/SurveyCommand.java new file mode 100644 index 0000000..a1a2f21 --- /dev/null +++ b/src/main/java/net/turniptales/discord/commands/SurveyCommand.java @@ -0,0 +1,104 @@ +package net.turniptales.discord.commands; + +import lombok.Data; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; + +import static java.awt.Color.CYAN; +import static java.util.Objects.nonNull; +import static java.util.concurrent.TimeUnit.SECONDS; +import static net.dv8tion.jda.api.Permission.ADMINISTRATOR; +import static net.dv8tion.jda.api.entities.emoji.Emoji.fromUnicode; +import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; +import static net.turniptales.discord.Config.BOT; + +public class SurveyCommand extends ListenerAdapter { + + public static Map pendingSurveys = new HashMap<>(); + + @Override + public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { + if (!e.getName().equals("umfrage") || !Objects.requireNonNull(e.getMember()).hasPermission(ADMINISTRATOR)) { + return; + } + + OptionMapping questionOptionMapping = e.getOption("question"); + OptionMapping descriptionOptionMapping = e.getOption("description"); + OptionMapping answer1OptionMapping = e.getOption("answer1"); + OptionMapping answer2OptionMapping = e.getOption("answer2"); + OptionMapping answer3OptionMapping = e.getOption("answer3"); + OptionMapping answer4OptionMapping = e.getOption("answer4"); + OptionMapping answer5OptionMapping = e.getOption("answer5"); + + List answers = Stream.of(answer1OptionMapping, answer2OptionMapping, answer3OptionMapping, answer4OptionMapping, answer5OptionMapping) + .filter(Objects::nonNull) + .map(OptionMapping::getAsString) + .toList(); + + if (nonNull(questionOptionMapping) && nonNull(descriptionOptionMapping) && answers.size() > 1) { + Survey survey = new Survey(questionOptionMapping.getAsString(), descriptionOptionMapping.getAsString(), answers); + + Member member = e.getMember(); + assert BOT != null; + + pendingSurveys.put(member, survey); + + e.replyEmbeds(survey.toEmbed(member)) + .setEphemeral(true) + .addActionRow(success("sendSurvey", "Starten")) + .queue(); + e.getHook().deleteOriginal().queueAfter(30, SECONDS); + } else { + e.reply("Es müssen mindestens eine Frage und zwei Antworten angegeben werden.").setEphemeral(true).queue(); + e.getHook().deleteOriginal().queueAfter(5, SECONDS); + } + } + + @Data + public static class Survey { + + private final String title; + private final String description; + private final List answers; + + public MessageEmbed toEmbed(Member member) { + EmbedBuilder embedBuilder = new EmbedBuilder() + .setColor(CYAN) + .setTitle(this.title) + .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setDescription(this.description) + .setFooter("Umfrage erstellt von " + member.getEffectiveName(), member.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + for (int i = 0; i < answers.size(); i++) { + embedBuilder.addField("Antwort " + (i + 1), this.answers.get(i), false); + } + + return embedBuilder.build(); + } + + public List getReactions() { + List emojis = List.of( + fromUnicode("U+0031 U+20E3"), + fromUnicode("U+0032 U+20E3"), + fromUnicode("U+0033 U+20E3"), + fromUnicode("U+0034 U+20E3"), + fromUnicode("U+0035 U+20E3") + ); + + return emojis.subList(0, this.answers.size()); + } + } +} diff --git a/src/main/java/net/turniptales/discord/events/TicketEventHandler.java b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java similarity index 84% rename from src/main/java/net/turniptales/discord/events/TicketEventHandler.java rename to src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java index bdba5b1..b17b29a 100644 --- a/src/main/java/net/turniptales/discord/events/TicketEventHandler.java +++ b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java @@ -10,10 +10,13 @@ import net.dv8tion.jda.api.interactions.components.Modal; import net.dv8tion.jda.api.interactions.components.text.TextInput; import net.dv8tion.jda.api.interactions.components.text.TextInputStyle; +import net.turniptales.discord.Config; import java.util.EnumSet; import java.util.Objects; +import static java.util.Optional.ofNullable; +import static java.util.concurrent.TimeUnit.SECONDS; import static net.dv8tion.jda.api.Permission.VIEW_CHANNEL; import static net.dv8tion.jda.api.entities.emoji.Emoji.fromUnicode; import static net.dv8tion.jda.api.interactions.components.Modal.create; @@ -25,8 +28,9 @@ import static net.turniptales.discord.Config.MODERATOR_ROLE; import static net.turniptales.discord.Config.SUPPORTER_ROLE; import static net.turniptales.discord.Config.TICKET_CATEGORY; +import static net.turniptales.discord.commands.SurveyCommand.pendingSurveys; -public class TicketEventHandler extends ListenerAdapter { +public class ButtonInteractionListener extends ListenerAdapter { @Override public void onButtonInteraction(ButtonInteractionEvent e) { @@ -86,6 +90,22 @@ public void onButtonInteraction(ButtonInteractionEvent e) { } } case "closeTicketAbort" -> e.getMessage().delete().queue(); + case "sendSurvey" -> { + Member member = e.getMember(); + assert member != null; + + ofNullable(pendingSurveys.remove(member)).ifPresentOrElse(survey -> { + assert Config.SURVEY_TEXT_CHANNEL != null; + Config.SURVEY_TEXT_CHANNEL.sendMessage("@everyone").setEmbeds(survey.toEmbed(member)) + .queue(message -> survey.getReactions().forEach(emoji -> message.addReaction(emoji).queue())); + + e.reply("Umfrage veröffentlicht!").setEphemeral(true).queue(); + e.getHook().deleteOriginal().queueAfter(5, SECONDS); + }, () -> { + e.reply("Es gibt keine Umfrage die veröffentlicht werden kann!").setEphemeral(true).queue(); + e.getHook().deleteOriginal().queueAfter(5, SECONDS); + }); + } } } diff --git a/src/main/java/net/turniptales/discord/events/MessageReactionListener.java b/src/main/java/net/turniptales/discord/events/MessageReactionListener.java new file mode 100644 index 0000000..cfd8043 --- /dev/null +++ b/src/main/java/net/turniptales/discord/events/MessageReactionListener.java @@ -0,0 +1,22 @@ +package net.turniptales.discord.events; + +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion; +import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +import static java.util.Objects.nonNull; +import static net.turniptales.discord.Config.SURVEY_TEXT_CHANNEL; + +public class MessageReactionListener extends ListenerAdapter { + + @Override + public void onMessageReactionAdd(MessageReactionAddEvent e) { + MessageChannelUnion channel = e.getChannel(); + User user = e.getUser(); + if (channel.equals(SURVEY_TEXT_CHANNEL) && nonNull(user) && !user.isBot()) { + channel.retrieveMessageById(e.getMessageIdLong()).queue(message -> message.getReactions() + .forEach(messageReaction -> messageReaction.removeReaction(user).queue())); + } + } +} From 1ae9f1d19f6000b07ce9c3f977054f905c0d75d0 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Mon, 12 Feb 2024 00:01:23 +0100 Subject: [PATCH 18/58] Fix votes not working for multi users --- .../discord/events/MessageReactionListener.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/turniptales/discord/events/MessageReactionListener.java b/src/main/java/net/turniptales/discord/events/MessageReactionListener.java index cfd8043..c8e555c 100644 --- a/src/main/java/net/turniptales/discord/events/MessageReactionListener.java +++ b/src/main/java/net/turniptales/discord/events/MessageReactionListener.java @@ -2,6 +2,7 @@ import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion; +import net.dv8tion.jda.api.entities.emoji.EmojiUnion; import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; @@ -15,8 +16,12 @@ public void onMessageReactionAdd(MessageReactionAddEvent e) { MessageChannelUnion channel = e.getChannel(); User user = e.getUser(); if (channel.equals(SURVEY_TEXT_CHANNEL) && nonNull(user) && !user.isBot()) { - channel.retrieveMessageById(e.getMessageIdLong()).queue(message -> message.getReactions() - .forEach(messageReaction -> messageReaction.removeReaction(user).queue())); + channel.retrieveMessageById(e.getMessageIdLong()).queue(message -> message.getReactions().forEach(messageReaction -> messageReaction.retrieveUsers().queue(users -> { + EmojiUnion emoji = messageReaction.getEmoji(); + if (users.contains(user) && !emoji.equals(e.getEmoji())) { + message.removeReaction(emoji, user).queue(); + } + }))); } } } From e6a398b85f74675b72a7e005cc2cd0af6257fa99 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Fri, 8 Mar 2024 17:34:12 +0100 Subject: [PATCH 19/58] Add giveaway feature --- .../discord/TurnipTalesDiscord.java | 7 ++ .../discord/commands/GiveawayCommand.java | 104 ++++++++++++++++++ .../events/ButtonInteractionListener.java | 10 +- 3 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 src/main/java/net/turniptales/discord/commands/GiveawayCommand.java diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index 6d83b32..6e9c19e 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -3,6 +3,7 @@ import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; +import net.turniptales.discord.commands.GiveawayCommand; import net.turniptales.discord.commands.StatsCommand; import net.turniptales.discord.commands.SurveyCommand; import net.turniptales.discord.commands.TicketCommand; @@ -49,6 +50,7 @@ private static void startDiscordBot() { .enableIntents(MESSAGE_CONTENT) .enableIntents(GUILD_MEMBERS) .addEventListeners( + new GiveawayCommand(), new StatsCommand(), new SurveyCommand(), new TicketCommand(), @@ -87,5 +89,10 @@ private static void startDiscordBot() { .upsertCommand("verify", "Verifiziert deinen Minecraft Account") .addOption(STRING, "code", "Verifizierungscode", true) .queue(); + + TURNIPTALES_BOT + .upsertCommand("giveaway", "Lost einen Spieler anhand der Reaktionen einer Nachricht aus") + .addOption(STRING, "message", "Nachricht mit den Reaktionen", true) + .queue(); } } diff --git a/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java b/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java new file mode 100644 index 0000000..fd4bb7a --- /dev/null +++ b/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java @@ -0,0 +1,104 @@ +package net.turniptales.discord.commands; + +import lombok.extern.log4j.Log4j2; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageReaction; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Random; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static java.util.Objects.nonNull; +import static java.util.concurrent.TimeUnit.SECONDS; +import static net.dv8tion.jda.api.Permission.ADMINISTRATOR; +import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; + +@Log4j2 +public class GiveawayCommand extends ListenerAdapter { + + public static Map giveaways = new HashMap<>(); + + @Override + public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { + if (!e.getName().equals("giveaway") || !Objects.requireNonNull(e.getMember()).hasPermission(ADMINISTRATOR)) { + return; + } + + OptionMapping messageOptionMapping = e.getOption("message"); + + if (nonNull(messageOptionMapping)) { + e.deferReply().setEphemeral(true).queue(); + + Message message = e.getChannel().retrieveMessageById(messageOptionMapping.getAsString()).complete(); + List reactions = message.getReactions(); + List usersWhoReacted = getUsersWhoReacted(reactions); + + List uniqueUsers = usersWhoReacted.stream() + .distinct() + .toList(); + + User winner = uniqueUsers.stream() + .filter(user -> !user.isBot()) + .toList().get(new Random().nextInt(uniqueUsers.size())); + + Giveaway giveaway = new Giveaway(message, uniqueUsers, winner); + giveaways.put(e.getUser(), giveaway); + + e.getHook() + .sendMessage("Reaktionen: " + usersWhoReacted.size() + " (" + reactions.size() + ")\nNutzer: " + uniqueUsers.size() + "\n\nGewinner: " + winner.getAsMention()) + .addActionRow(success("publishWinner", "Gewinner veröffentlichen")) + .queue(); + } else { + e.reply("Es muss eine Nachrichten ID angegeben werden.").setEphemeral(true).queue(); + e.getHook().deleteOriginal().queueAfter(5, SECONDS); + } + } + + public List getUsersWhoReacted(List reactions) { + List>> messageReactionUsersFuture = new ArrayList<>(); + + reactions.forEach(reaction -> { + CompletableFuture> reactionUsersFuture = new CompletableFuture<>(); + reaction.retrieveUsers().queue(reactionUsersFuture::complete); + messageReactionUsersFuture.add(reactionUsersFuture); + }); + + return messageReactionUsersFuture.stream() + .map(future -> { + try { + return future.get(); + } catch (InterruptedException | ExecutionException e) { + log.error(e); + return null; + } + }) + .filter(Objects::nonNull) + .flatMap(List::stream) + .toList(); + } + + public static class Giveaway { + private final Message message; + private final List users; + private final User winner; + + public Giveaway(Message message, List users, User winner) { + this.message = message; + this.users = users; + this.winner = winner; + } + + public void publishWinner() { + this.message.reply("@here\n:tada: **Ein Gewinner wurde gezogen!** :tada:\n\nAus `" + this.users.size() + "` Teilnehmern wurde " + this.winner.getAsMention() + " ausgelost. Herzlichen Glückwunsch!").queue(); + } + } +} diff --git a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java index b17b29a..492d9bd 100644 --- a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java +++ b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java @@ -28,6 +28,7 @@ import static net.turniptales.discord.Config.MODERATOR_ROLE; import static net.turniptales.discord.Config.SUPPORTER_ROLE; import static net.turniptales.discord.Config.TICKET_CATEGORY; +import static net.turniptales.discord.commands.GiveawayCommand.giveaways; import static net.turniptales.discord.commands.SurveyCommand.pendingSurveys; public class ButtonInteractionListener extends ListenerAdapter { @@ -106,6 +107,11 @@ public void onButtonInteraction(ButtonInteractionEvent e) { e.getHook().deleteOriginal().queueAfter(5, SECONDS); }); } + case "publishWinner" -> { + giveaways.get(e.getUser()).publishWinner(); + e.reply("Gewinner veröffentlicht!").setEphemeral(true).queue(); + e.getHook().deleteOriginal().queueAfter(5, SECONDS); + } } } @@ -114,7 +120,7 @@ public void onModalInteraction(ModalInteractionEvent e) { String modalId = e.getModalId(); switch (modalId) { - case "ticket_modal": + case "ticket_modal" -> { Member member = e.getMember(); assert member != null; String memberId = member.getId(); @@ -138,7 +144,7 @@ public void onModalInteraction(ModalInteractionEvent e) { + "Anliegen: " + log) .addActionRow(success("closeTicket", "Ticket schließen").withEmoji(fromUnicode("U+1F512"))) .queue(message -> e.reply("Du hast ein Ticket erstellt: " + message.getJumpUrl()).setEphemeral(true).queue())); - break; + } } } } From d9621eca67c4bbc0a4eb78cafab84cf751aead1e Mon Sep 17 00:00:00 2001 From: rettichlp Date: Fri, 22 Mar 2024 21:23:39 +0100 Subject: [PATCH 20/58] Add senior moderator to tickets --- src/main/java/net/turniptales/discord/Config.java | 1 + .../turniptales/discord/events/ButtonInteractionListener.java | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/main/java/net/turniptales/discord/Config.java b/src/main/java/net/turniptales/discord/Config.java index fa16986..e664b36 100644 --- a/src/main/java/net/turniptales/discord/Config.java +++ b/src/main/java/net/turniptales/discord/Config.java @@ -21,6 +21,7 @@ public class Config { // player roles public static final Role PLAYER_ROLE = GUILD.getRoleById("1190675464549847110"); // team roles + public static final Role SENIOR_MODERATOR_ROLE = GUILD.getRoleById("1208149723547050004"); public static final Role MODERATOR_ROLE = GUILD.getRoleById("1025864289346658355"); public static final Role SUPPORTER_ROLE = GUILD.getRoleById("1009477020427747408"); // user time roles diff --git a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java index 492d9bd..25cfef0 100644 --- a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java +++ b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java @@ -26,6 +26,7 @@ import static net.dv8tion.jda.api.interactions.components.text.TextInputStyle.PARAGRAPH; import static net.turniptales.discord.Config.GUILD; import static net.turniptales.discord.Config.MODERATOR_ROLE; +import static net.turniptales.discord.Config.SENIOR_MODERATOR_ROLE; import static net.turniptales.discord.Config.SUPPORTER_ROLE; import static net.turniptales.discord.Config.TICKET_CATEGORY; import static net.turniptales.discord.commands.GiveawayCommand.giveaways; @@ -130,12 +131,14 @@ public void onModalInteraction(ModalInteractionEvent e) { String log = e.getValue("topic_input").getAsString(); assert GUILD != null; + assert SENIOR_MODERATOR_ROLE != null; assert MODERATOR_ROLE != null; assert SUPPORTER_ROLE != null; TICKET_CATEGORY.createTextChannel("ticket-" + userName) .setTopic("Ticket von " + userName + " (" + memberId + ")") .addPermissionOverride(GUILD.getPublicRole(), null, EnumSet.of(VIEW_CHANNEL)) .addPermissionOverride(member, EnumSet.of(VIEW_CHANNEL), null) + .addPermissionOverride(SENIOR_MODERATOR_ROLE, EnumSet.of(VIEW_CHANNEL), null) .addPermissionOverride(MODERATOR_ROLE, EnumSet.of(VIEW_CHANNEL), null) .addPermissionOverride(SUPPORTER_ROLE, EnumSet.of(VIEW_CHANNEL), null) .queue(textChannel -> textChannel From 8d2c963546e422750cb9ea5058482aecbfdae82d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 22:01:05 +0000 Subject: [PATCH 21/58] Bump org.apache.tomcat.embed:tomcat-embed-core from 10.1.17 to 10.1.19 Bumps org.apache.tomcat.embed:tomcat-embed-core from 10.1.17 to 10.1.19. --- updated-dependencies: - dependency-name: org.apache.tomcat.embed:tomcat-embed-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f1354f2..e9a4976 100644 --- a/pom.xml +++ b/pom.xml @@ -40,7 +40,7 @@ org.apache.tomcat.embed tomcat-embed-core - 10.1.17 + 10.1.19 From 0a1b958927ffb5925ac5d23a40a4575202fa7b65 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Wed, 3 Apr 2024 00:59:32 +0200 Subject: [PATCH 22/58] Update player stats model --- .../discord/TurnipTalesDiscord.java | 5 ++ .../discord/commands/StatsCommand.java | 76 +++++++++---------- .../discord/commands/VerifyCommand.java | 8 +- .../turniptales/discord/common/api/Api.java | 35 ++++++--- .../common/api/model/DiscordPlayerStats.java | 31 ++++++++ .../discord/common/api/model/PlayerStats.java | 28 ------- .../common/api/model/PunishmentData.java | 51 +++++++++++++ .../common/api/model/stats/Contract.java | 21 ----- .../api/model/stats/PunishmentData.java | 39 ---------- .../common/api/model/stats/RoleplayData.java | 42 ---------- 10 files changed, 152 insertions(+), 184 deletions(-) create mode 100644 src/main/java/net/turniptales/discord/common/api/model/DiscordPlayerStats.java delete mode 100644 src/main/java/net/turniptales/discord/common/api/model/PlayerStats.java create mode 100644 src/main/java/net/turniptales/discord/common/api/model/PunishmentData.java delete mode 100644 src/main/java/net/turniptales/discord/common/api/model/stats/Contract.java delete mode 100644 src/main/java/net/turniptales/discord/common/api/model/stats/PunishmentData.java delete mode 100644 src/main/java/net/turniptales/discord/common/api/model/stats/RoleplayData.java diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index 6e9c19e..58814b7 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -17,7 +17,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.time.ZoneId; + import static java.lang.System.currentTimeMillis; +import static java.time.ZoneId.of; import static net.dv8tion.jda.api.interactions.commands.OptionType.STRING; import static net.dv8tion.jda.api.interactions.commands.OptionType.USER; import static net.dv8tion.jda.api.requests.GatewayIntent.GUILD_MEMBERS; @@ -31,9 +34,11 @@ public class TurnipTalesDiscord implements WebMvcConfigurer { public static JDA TURNIPTALES_BOT; + public static ZoneId ZONE_ID; public static void main(String[] args) { SpringApplication.run(TurnipTalesDiscord.class, args); + ZONE_ID = of("Europe/Berlin"); long discordBotStartTime = currentTimeMillis(); log.info("Discord bot starting"); diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index 9ce611b..1b5a84c 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -9,9 +9,8 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.turniptales.discord.common.api.Api; -import net.turniptales.discord.common.api.model.PlayerStats; -import net.turniptales.discord.common.api.model.stats.PunishmentData; -import net.turniptales.discord.common.api.model.stats.RoleplayData; +import net.turniptales.discord.common.api.model.DiscordPlayerStats; +import net.turniptales.discord.common.api.model.PunishmentData; import java.util.Date; import java.util.List; @@ -22,7 +21,6 @@ import static java.util.Objects.nonNull; import static java.util.concurrent.TimeUnit.SECONDS; import static net.turniptales.discord.Config.BOT; -import static net.turniptales.discord.common.api.model.stats.RoleplayData.Gender.MAN; public class StatsCommand extends ListenerAdapter { @@ -38,8 +36,8 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { Member member = e.getMember(); if (nonNull(playerOptionMapping)) { try { - PlayerStats playerStats = api.getPlayerStatsByDiscordUserId(playerOptionMapping.getAsUser().getIdLong()); - MessageEmbed publicPlayerStats = isTicketChannel(e.getChannel()) ? getPrivatePlayerStats(playerStats, member) : getPublicPlayerStats(playerStats, member); + DiscordPlayerStats discordPlayerStats = api.getPlayerStatsByDiscordUserId(playerOptionMapping.getAsUser().getIdLong(), null); + MessageEmbed publicPlayerStats = isTicketChannel(e.getChannel()) ? getPrivatePlayerStats(discordPlayerStats, member) : getPublicPlayerStats(discordPlayerStats, member); e.replyEmbeds(publicPlayerStats).queue(); } catch (Exception ex) { e.reply("Der angegebene Spieler hat seinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); @@ -47,8 +45,8 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { } } else { try { - PlayerStats playerStats = api.getPlayerStatsByDiscordUserId(e.getUser().getIdLong()); - MessageEmbed privatePlayerStats = getPrivatePlayerStats(playerStats, member); + DiscordPlayerStats discordPlayerStats = api.getPlayerStatsByDiscordUserId(e.getUser().getIdLong(), null); + MessageEmbed privatePlayerStats = getPrivatePlayerStats(discordPlayerStats, member); e.replyEmbeds(privatePlayerStats).setEphemeral(true).queue(); } catch (Exception ex) { e.reply("Du hast deinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); @@ -63,68 +61,64 @@ && nonNull(textChannel.getTopic()) && textChannel.getTopic().contains("Ticket von "); } - private MessageEmbed getPublicPlayerStats(PlayerStats playerStats, Member member) { - RoleplayData roleplayData = playerStats.getRoleplayData(); + private MessageEmbed getPublicPlayerStats(DiscordPlayerStats discordPlayerStats, Member member) { + return getDefaultEmbedBuilder(discordPlayerStats, member) + .addField("Level", valueOf(discordPlayerStats.getLevel()), true) + .addField("Fraktion:", discordPlayerStats.getGroup(), true) + .addField("Kennt Spieler", valueOf(discordPlayerStats.getKnownPlayerCount()), true) - return getDefaultEmbedBuilder(playerStats, member) - .addField("Level", valueOf(playerStats.getLevel()), true) - .addField("Fraktion:", playerStats.getFaction(), true) - .addField("Kennt Spieler", valueOf(playerStats.getKnownPlayerCount()), true) - - .addField("Steckbrief", getCharacteristics(roleplayData), false) + .addField("Steckbrief", getCharacteristics(discordPlayerStats), false) .addBlankField(false) - .addField("Häuser:", getHouses(playerStats.getHouses()), true) - .addField("Autos:", getCars(playerStats.getCars()), true) + .addField("Häuser:", getHouses(discordPlayerStats.getHouses()), true) + .addField("Autos:", getCars(discordPlayerStats.getCars()), true) .build(); } - private MessageEmbed getPrivatePlayerStats(PlayerStats playerStats, Member member) { - RoleplayData roleplayData = playerStats.getRoleplayData(); - - return getDefaultEmbedBuilder(playerStats, member) - .addField("Level", valueOf(playerStats.getLevel()), true) - .addField("Fraktion:", playerStats.getFaction(), true) - .addField("Kennt Spieler", valueOf(playerStats.getKnownPlayerCount()), true) + private MessageEmbed getPrivatePlayerStats(DiscordPlayerStats discordPlayerStats, Member member) { + return getDefaultEmbedBuilder(discordPlayerStats, member) + .addField("Level", valueOf(discordPlayerStats.getLevel()), true) + .addField("Fraktion:", discordPlayerStats.getGroup(), true) + .addField("Kennt Spieler", valueOf(discordPlayerStats.getKnownPlayerCount()), true) - .addField("Steckbrief", getCharacteristics(roleplayData), false) - .addField("Finanzen", getBalances(roleplayData), true) - .addField("Bestrafung", getPunishments(playerStats.getPunishmentData()), true) + .addField("Steckbrief", getCharacteristics(discordPlayerStats), false) + .addField("Finanzen", getBalances(discordPlayerStats), true) + .addField("Bestrafung", getPunishments(discordPlayerStats.getPunishmentData()), true) .addBlankField(false) - .addField("Häuser:", getHouses(playerStats.getHouses()), true) - .addField("Autos:", getCars(playerStats.getCars()), true) + .addField("Häuser:", getHouses(discordPlayerStats.getHouses()), true) + .addField("Autos:", getCars(discordPlayerStats.getCars()), true) .build(); } - private EmbedBuilder getDefaultEmbedBuilder(PlayerStats playerStats, Member member) { + private EmbedBuilder getDefaultEmbedBuilder(DiscordPlayerStats discordPlayerStats, Member member) { assert BOT != null; return new EmbedBuilder() .setColor(CYAN) - .setThumbnail("https://minotar.net/helm/" + playerStats.getMinecraftUuid() + "/300.png") + .setThumbnail("https://minotar.net/helm/" + discordPlayerStats.getMinecraftUuid() + "/300.png") .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) - .setTitle("Statistiken von " + playerStats.getMinecraftName()) - .setDescription("**Role**: " + playerStats.getRole()) + .setTitle("Statistiken von " + discordPlayerStats.getMinecraftName()) + .setDescription("**Role**: " + discordPlayerStats.getRole()) .setFooter(member.getEffectiveName(), member.getEffectiveAvatarUrl()) .setTimestamp(new Date().toInstant()); } - private String getCharacteristics(RoleplayData roleplayData) { + private String getCharacteristics(DiscordPlayerStats discordPlayerStats) { return """ **Name**: %s **Alter**: %s **Geschlecht**: %s """ - .formatted(roleplayData.getFirstname() + " " + roleplayData.getLastname(), - "20", - roleplayData.getGender().equals(MAN) ? ":male_sign:" : ":female_sign:"); + .formatted(discordPlayerStats.getRoleplayName(), + discordPlayerStats.getAge(), + discordPlayerStats.getGender().equals("MAN") ? ":male_sign:" : ":female_sign:"); } - private String getBalances(RoleplayData roleplayData) { + private String getBalances(DiscordPlayerStats discordPlayerStats) { return """ **Bank**: %s$ **Bargeld**: %s$ **PayPal**: %s$ """ - .formatted(roleplayData.getBankBalance(), roleplayData.getCashBalance(), roleplayData.getPayPalBalance()); + .formatted(discordPlayerStats.getBankBalance(), discordPlayerStats.getCashBalance(), discordPlayerStats.getPalPayBalance()); } private String getPunishments(PunishmentData punishmentData) { @@ -136,7 +130,7 @@ private String getPunishments(PunishmentData punishmentData) { **Auto-Sperre**: %s **Checkpoints**: %s """ - .formatted(punishmentData.isWeaponBlockActive(), punishmentData.isFactionBlockActive(), punishmentData.isSkillBlockActive(), punishmentData.isAdBlockActive(), punishmentData.isCarBlockActive(), punishmentData.getCheckpointsLeft()); + .formatted(!punishmentData.noWeaponBlockActive(), !punishmentData.noGroupBlockActive(), !punishmentData.noSkillBlockActive(), !punishmentData.noAdBlockActive(), !punishmentData.noCarBlockActive(), punishmentData.getCheckpointsLeft()); } private String getHouses(List houses) { diff --git a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java index 96202b4..1277fda 100644 --- a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java @@ -4,7 +4,7 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.turniptales.discord.common.api.Api; -import net.turniptales.discord.common.api.model.PlayerStats; +import net.turniptales.discord.common.api.model.DiscordPlayerStats; import static java.util.Objects.isNull; import static java.util.Objects.nonNull; @@ -24,10 +24,10 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { return; } - PlayerStats playerStats = new Api().getPlayerStatsByDiscordUserIdVerify(e.getUser().getIdLong(), codeOptionMapping.getAsString()); + DiscordPlayerStats discordPlayerStats = new Api().getPlayerStatsByDiscordUserId(e.getUser().getIdLong(), codeOptionMapping.getAsString()); String message; - if (nonNull(playerStats)) { - message = "Du hast deinen Discord Account mit dem Minecraft Account " + playerStats.getMinecraftName() + " verknüpft!\nDiese Nachricht zerstört sich gleich von selbst..."; + if (nonNull(discordPlayerStats)) { + message = "Du hast deinen Discord Account mit dem Minecraft Account " + discordPlayerStats.getMinecraftName() + " verknüpft!\nDiese Nachricht zerstört sich gleich von selbst..."; } else { message = "Dein Discord Account konnte nicht mit deinem Minecraft Account verknüpft werden."; } diff --git a/src/main/java/net/turniptales/discord/common/api/Api.java b/src/main/java/net/turniptales/discord/common/api/Api.java index ecd5748..fbab20b 100644 --- a/src/main/java/net/turniptales/discord/common/api/Api.java +++ b/src/main/java/net/turniptales/discord/common/api/Api.java @@ -1,11 +1,21 @@ package net.turniptales.discord.common.api; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializer; import lombok.Data; import lombok.extern.log4j.Log4j2; -import net.turniptales.discord.common.api.model.PlayerStats; +import net.turniptales.discord.common.api.model.DiscordPlayerStats; +import org.jetbrains.annotations.Nullable; import org.springframework.web.reactive.function.client.WebClient; +import java.time.ZonedDateTime; + +import static java.time.ZonedDateTime.parse; +import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME; +import static java.util.Optional.ofNullable; import static org.springframework.http.HttpMethod.GET; @Log4j2 @@ -13,24 +23,31 @@ public class Api { /** - * {@link PlayerStats} + * {@link DiscordPlayerStats} */ - public PlayerStats getPlayerStatsByDiscordUserId(long userId) { - return parseGetRequest("/" + userId, PlayerStats.class); - } + public DiscordPlayerStats getPlayerStatsByDiscordUserId(long userId, @Nullable String discordCode) { + String code = ofNullable(discordCode) + .map(c -> "?discordCode=" + c) + .orElse(""); - public PlayerStats getPlayerStatsByDiscordUserIdVerify(long userId, String discordCode) { - return parseGetRequest("/" + userId + "?discordCode=" + discordCode, PlayerStats.class); + return parseGetRequest("/" + userId + code, DiscordPlayerStats.class); } /** * Request */ private T parseGetRequest(String url, Class model) { - Gson gson = new Gson(); + Gson gson = getGson(); return gson.fromJson(sendGetRequest(url), model); } + private Gson getGson() { + return new GsonBuilder() + .registerTypeAdapter(ZonedDateTime.class, (JsonDeserializer) (json, type, jsonDeserializationContext) -> parse(json.getAsJsonPrimitive().getAsString())) + .registerTypeAdapter(ZonedDateTime.class, (JsonSerializer) (date, type, jsonSerializationContext) -> new JsonPrimitive(date.format(ISO_ZONED_DATE_TIME))) + .create(); + } + private String sendGetRequest(String url) { return getClient(url).method(GET) .retrieve() @@ -40,7 +57,7 @@ private String sendGetRequest(String url) { private WebClient getClient(String url) { return WebClient.builder() - .baseUrl("https://rettichlp.de:7100/turniptalesapi/v1/verification/discord" + url) + .baseUrl("https://turniptales.net:7200/turniptalesapi/v1/verification/discord" + url) .defaultHeader("Authorization", "Basic dHVybmlwdGFsZXMtYXBpdXNlcjoqYnp0OThjV3EvLCckOT41SEN7NlEtTycralZFZmprMQ==") .build(); } diff --git a/src/main/java/net/turniptales/discord/common/api/model/DiscordPlayerStats.java b/src/main/java/net/turniptales/discord/common/api/model/DiscordPlayerStats.java new file mode 100644 index 0000000..5f3dedc --- /dev/null +++ b/src/main/java/net/turniptales/discord/common/api/model/DiscordPlayerStats.java @@ -0,0 +1,31 @@ +package net.turniptales.discord.common.api.model; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; +import java.util.UUID; + +@Data +@Builder +public class DiscordPlayerStats { + + // data + private UUID minecraftUuid; + private String minecraftName; + private String role; + private int level; + private String group; + private int knownPlayerCount; + // characteristics + private String roleplayName; + private int age; + private String gender; + // balances + private double bankBalance; + private double cashBalance; + private double palPayBalance; + private PunishmentData punishmentData; + private List houses; + private List cars; +} diff --git a/src/main/java/net/turniptales/discord/common/api/model/PlayerStats.java b/src/main/java/net/turniptales/discord/common/api/model/PlayerStats.java deleted file mode 100644 index 39c5ac2..0000000 --- a/src/main/java/net/turniptales/discord/common/api/model/PlayerStats.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.turniptales.discord.common.api.model; - -import lombok.AllArgsConstructor; -import lombok.Data; -import net.turniptales.discord.common.api.model.stats.Contract; -import net.turniptales.discord.common.api.model.stats.PunishmentData; -import net.turniptales.discord.common.api.model.stats.RoleplayData; - -import java.util.List; -import java.util.UUID; - -@Data -@AllArgsConstructor -public class PlayerStats { - - private UUID minecraftUuid; - private String minecraftName; - private String faction; - private int level; - private boolean online; - private PunishmentData punishmentData; - private RoleplayData roleplayData; - private List houses; - private List contracts; - private String role; - private int knownPlayerCount; - private List cars; -} diff --git a/src/main/java/net/turniptales/discord/common/api/model/PunishmentData.java b/src/main/java/net/turniptales/discord/common/api/model/PunishmentData.java new file mode 100644 index 0000000..02df01d --- /dev/null +++ b/src/main/java/net/turniptales/discord/common/api/model/PunishmentData.java @@ -0,0 +1,51 @@ +package net.turniptales.discord.common.api.model; + +import lombok.Builder; +import lombok.Data; +import org.jetbrains.annotations.Nullable; + +import java.time.ZonedDateTime; +import java.util.List; + +import static java.time.ZonedDateTime.now; +import static java.util.Objects.nonNull; +import static net.turniptales.discord.TurnipTalesDiscord.ZONE_ID; + +@Data +@Builder +public class PunishmentData { + + private long id; + @Nullable + private ZonedDateTime weaponBlockUntilDateTime; + @Nullable + private ZonedDateTime groupBlockUntilDateTime; + @Nullable + private ZonedDateTime skillBlockUntilDateTime; + @Nullable + private ZonedDateTime adBlockUntilDateTime; + @Nullable + private ZonedDateTime carBlockUntilDateTime; + private int checkpointsLeft; + private List log; + + public boolean noWeaponBlockActive() { + return !nonNull(this.weaponBlockUntilDateTime) || this.weaponBlockUntilDateTime.isBefore(now(ZONE_ID)); + } + + public boolean noGroupBlockActive() { + return !nonNull(this.groupBlockUntilDateTime) || this.groupBlockUntilDateTime.isBefore(now(ZONE_ID)); + } + + public boolean noSkillBlockActive() { + return !nonNull(this.skillBlockUntilDateTime) || this.skillBlockUntilDateTime.isBefore(now(ZONE_ID)); + } + + public boolean noAdBlockActive() { + return !nonNull(this.adBlockUntilDateTime) || this.adBlockUntilDateTime.isBefore(now(ZONE_ID)); + } + + public boolean noCarBlockActive() { + return !nonNull(this.carBlockUntilDateTime) || this.carBlockUntilDateTime.isBefore(now(ZONE_ID)); + } +} diff --git a/src/main/java/net/turniptales/discord/common/api/model/stats/Contract.java b/src/main/java/net/turniptales/discord/common/api/model/stats/Contract.java deleted file mode 100644 index 280215d..0000000 --- a/src/main/java/net/turniptales/discord/common/api/model/stats/Contract.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.turniptales.discord.common.api.model.stats; - -import lombok.Data; - -import java.util.UUID; - -@Data -public class Contract { - - private long id; - private long startDate; - private long endDate; - private UUID owner; - private UUID partner; - private long payDayBalance; // is paid every pay day by partner - private long oneTimeBalance; // is paid at endDate by partner - - public boolean isPayedEveryPayDay(UUID minecraftUuid) { - return this.partner.equals(minecraftUuid) && this.payDayBalance > 0; - } -} diff --git a/src/main/java/net/turniptales/discord/common/api/model/stats/PunishmentData.java b/src/main/java/net/turniptales/discord/common/api/model/stats/PunishmentData.java deleted file mode 100644 index a716c71..0000000 --- a/src/main/java/net/turniptales/discord/common/api/model/stats/PunishmentData.java +++ /dev/null @@ -1,39 +0,0 @@ -package net.turniptales.discord.common.api.model.stats; - -import lombok.Data; - -import java.util.Date; -import java.util.List; - -@Data -public class PunishmentData { - - private long id; - private long weaponBlockUntil; - private long factionBlockUntil; - private long skillBlockUntil; - private long adBlockUntil; - private long carBlockUntil; - private int checkpointsLeft; - private List log; - - public boolean isWeaponBlockActive() { - return new Date(this.weaponBlockUntil).after(new Date()); - } - - public boolean isFactionBlockActive() { - return new Date(this.factionBlockUntil).after(new Date()); - } - - public boolean isSkillBlockActive() { - return new Date(this.skillBlockUntil).after(new Date()); - } - - public boolean isAdBlockActive() { - return new Date(this.adBlockUntil).after(new Date()); - } - - public boolean isCarBlockActive() { - return new Date(this.carBlockUntil).after(new Date()); - } -} diff --git a/src/main/java/net/turniptales/discord/common/api/model/stats/RoleplayData.java b/src/main/java/net/turniptales/discord/common/api/model/stats/RoleplayData.java deleted file mode 100644 index a287bca..0000000 --- a/src/main/java/net/turniptales/discord/common/api/model/stats/RoleplayData.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.turniptales.discord.common.api.model.stats; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.Getter; - -@Data -public class RoleplayData { - - private long id; - private String firstname; - private String lastname; - private Gender gender; - private long birthday; - private double bankBalance; - private double cashBalance; - private double payPalBalance; - private double wantedPercentage; - private double hydration; - - public String getRoleplayDisplayName() { - return this.firstname + " " + this.lastname; - } - - @Getter - @AllArgsConstructor - public enum Gender { - - MAN("Männlich", "Herr", "Vater", "Sohn", "Bruder"), - FEMALE("Weiblich", "Frau", "Mutter", "Tochter", "Schwester"); - - private final String adjective; - private final String salutation; - private final String parent; - private final String children; - private final String sibling; - - public String getUnknownName() { - return this.equals(MAN) ? "Fremder" : "Fremde"; - } - } -} From 43524057eb146673eaecfd1d7ce6b3bbea4613f2 Mon Sep 17 00:00:00 2001 From: rettichlp Date: Wed, 3 Apr 2024 01:04:36 +0200 Subject: [PATCH 23/58] Update formatting of money balance --- .../net/turniptales/discord/commands/StatsCommand.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index 1b5a84c..1ad6998 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -12,18 +12,24 @@ import net.turniptales.discord.common.api.model.DiscordPlayerStats; import net.turniptales.discord.common.api.model.PunishmentData; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; import java.util.Date; import java.util.List; import java.util.StringJoiner; import static java.awt.Color.CYAN; import static java.lang.String.valueOf; +import static java.util.Locale.US; import static java.util.Objects.nonNull; import static java.util.concurrent.TimeUnit.SECONDS; import static net.turniptales.discord.Config.BOT; public class StatsCommand extends ListenerAdapter { + public static final DecimalFormatSymbols US_SYMBOLS = DecimalFormatSymbols.getInstance(US); + public static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("###.##", US_SYMBOLS); + @Override public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { if (!e.getName().equals("stats")) { @@ -118,7 +124,7 @@ private String getBalances(DiscordPlayerStats discordPlayerStats) { **Bargeld**: %s$ **PayPal**: %s$ """ - .formatted(discordPlayerStats.getBankBalance(), discordPlayerStats.getCashBalance(), discordPlayerStats.getPalPayBalance()); + .formatted(DECIMAL_FORMAT.format(discordPlayerStats.getBankBalance()), DECIMAL_FORMAT.format(discordPlayerStats.getCashBalance()), DECIMAL_FORMAT.format(discordPlayerStats.getPalPayBalance())); } private String getPunishments(PunishmentData punishmentData) { From 6dc49c492dca99fb0d3504641e5bb63d3327d76c Mon Sep 17 00:00:00 2001 From: rettichlp Date: Mon, 29 Apr 2024 11:40:40 +0200 Subject: [PATCH 24/58] Fix project inspection findings --- .../java/net/turniptales/discord/commands/GiveawayCommand.java | 2 +- .../java/net/turniptales/discord/commands/SurveyCommand.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java b/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java index fd4bb7a..334d343 100644 --- a/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java +++ b/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java @@ -25,7 +25,7 @@ @Log4j2 public class GiveawayCommand extends ListenerAdapter { - public static Map giveaways = new HashMap<>(); + public static final Map giveaways = new HashMap<>(); @Override public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { diff --git a/src/main/java/net/turniptales/discord/commands/SurveyCommand.java b/src/main/java/net/turniptales/discord/commands/SurveyCommand.java index a1a2f21..c6e5fb4 100644 --- a/src/main/java/net/turniptales/discord/commands/SurveyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/SurveyCommand.java @@ -26,7 +26,7 @@ public class SurveyCommand extends ListenerAdapter { - public static Map pendingSurveys = new HashMap<>(); + public static final Map pendingSurveys = new HashMap<>(); @Override public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { From b995356ea3064cf9f115a07d87433dd0759d489c Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 3 Jul 2024 19:21:33 +0200 Subject: [PATCH 25/58] Sync with new ConnectionDataValue from api --- .../discord/commands/StatsCommand.java | 68 +++++++++---------- .../discord/commands/VerifyCommand.java | 16 +++-- .../turniptales/discord/common/api/Api.java | 35 ++++++---- ...yerStats.java => ConnectionDataValue.java} | 13 +++- .../common/api/model/PunishmentData.java | 1 - 5 files changed, 75 insertions(+), 58 deletions(-) rename src/main/java/net/turniptales/discord/common/api/model/{DiscordPlayerStats.java => ConnectionDataValue.java} (71%) diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index 1ad6998..8e0dfd5 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -9,7 +9,7 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.turniptales.discord.common.api.Api; -import net.turniptales.discord.common.api.model.DiscordPlayerStats; +import net.turniptales.discord.common.api.model.ConnectionDataValue; import net.turniptales.discord.common.api.model.PunishmentData; import java.text.DecimalFormat; @@ -42,8 +42,8 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { Member member = e.getMember(); if (nonNull(playerOptionMapping)) { try { - DiscordPlayerStats discordPlayerStats = api.getPlayerStatsByDiscordUserId(playerOptionMapping.getAsUser().getIdLong(), null); - MessageEmbed publicPlayerStats = isTicketChannel(e.getChannel()) ? getPrivatePlayerStats(discordPlayerStats, member) : getPublicPlayerStats(discordPlayerStats, member); + ConnectionDataValue connectionDataValue = api.getData(e.getUser().getIdLong()); + MessageEmbed publicPlayerStats = isTicketChannel(e.getChannel()) ? getPrivatePlayerStats(connectionDataValue, member) : getPublicPlayerStats(connectionDataValue, member); e.replyEmbeds(publicPlayerStats).queue(); } catch (Exception ex) { e.reply("Der angegebene Spieler hat seinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); @@ -51,8 +51,8 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { } } else { try { - DiscordPlayerStats discordPlayerStats = api.getPlayerStatsByDiscordUserId(e.getUser().getIdLong(), null); - MessageEmbed privatePlayerStats = getPrivatePlayerStats(discordPlayerStats, member); + ConnectionDataValue connectionDataValue = api.getData(e.getUser().getIdLong()); + MessageEmbed privatePlayerStats = getPrivatePlayerStats(connectionDataValue, member); e.replyEmbeds(privatePlayerStats).setEphemeral(true).queue(); } catch (Exception ex) { e.reply("Du hast deinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); @@ -67,64 +67,64 @@ && nonNull(textChannel.getTopic()) && textChannel.getTopic().contains("Ticket von "); } - private MessageEmbed getPublicPlayerStats(DiscordPlayerStats discordPlayerStats, Member member) { - return getDefaultEmbedBuilder(discordPlayerStats, member) - .addField("Level", valueOf(discordPlayerStats.getLevel()), true) - .addField("Fraktion:", discordPlayerStats.getGroup(), true) - .addField("Kennt Spieler", valueOf(discordPlayerStats.getKnownPlayerCount()), true) + private MessageEmbed getPublicPlayerStats(ConnectionDataValue connectionDataValue, Member member) { + return getDefaultEmbedBuilder(connectionDataValue, member) + .addField("Level", valueOf(connectionDataValue.getLevel()), true) + .addField("Fraktion:", connectionDataValue.getGroup(), true) + .addField("Kennt Spieler", valueOf(connectionDataValue.getKnownPlayerCount()), true) - .addField("Steckbrief", getCharacteristics(discordPlayerStats), false) + .addField("Steckbrief", getCharacteristics(connectionDataValue), false) .addBlankField(false) - .addField("Häuser:", getHouses(discordPlayerStats.getHouses()), true) - .addField("Autos:", getCars(discordPlayerStats.getCars()), true) + .addField("Häuser:", getHouses(connectionDataValue.getHouses()), true) + .addField("Autos:", getCars(connectionDataValue.getCars()), true) .build(); } - private MessageEmbed getPrivatePlayerStats(DiscordPlayerStats discordPlayerStats, Member member) { - return getDefaultEmbedBuilder(discordPlayerStats, member) - .addField("Level", valueOf(discordPlayerStats.getLevel()), true) - .addField("Fraktion:", discordPlayerStats.getGroup(), true) - .addField("Kennt Spieler", valueOf(discordPlayerStats.getKnownPlayerCount()), true) + private MessageEmbed getPrivatePlayerStats(ConnectionDataValue connectionDataValue, Member member) { + return getDefaultEmbedBuilder(connectionDataValue, member) + .addField("Level", valueOf(connectionDataValue.getLevel()), true) + .addField("Fraktion:", connectionDataValue.getGroup(), true) + .addField("Kennt Spieler", valueOf(connectionDataValue.getKnownPlayerCount()), true) - .addField("Steckbrief", getCharacteristics(discordPlayerStats), false) - .addField("Finanzen", getBalances(discordPlayerStats), true) - .addField("Bestrafung", getPunishments(discordPlayerStats.getPunishmentData()), true) + .addField("Steckbrief", getCharacteristics(connectionDataValue), false) + .addField("Finanzen", getBalances(connectionDataValue), true) + .addField("Bestrafung", getPunishments(connectionDataValue.getPunishmentData()), true) .addBlankField(false) - .addField("Häuser:", getHouses(discordPlayerStats.getHouses()), true) - .addField("Autos:", getCars(discordPlayerStats.getCars()), true) + .addField("Häuser:", getHouses(connectionDataValue.getHouses()), true) + .addField("Autos:", getCars(connectionDataValue.getCars()), true) .build(); } - private EmbedBuilder getDefaultEmbedBuilder(DiscordPlayerStats discordPlayerStats, Member member) { + private EmbedBuilder getDefaultEmbedBuilder(ConnectionDataValue connectionDataValue, Member member) { assert BOT != null; return new EmbedBuilder() .setColor(CYAN) - .setThumbnail("https://minotar.net/helm/" + discordPlayerStats.getMinecraftUuid() + "/300.png") + .setThumbnail("https://minotar.net/helm/" + connectionDataValue.getMinecraftUuid() + "/300.png") .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) - .setTitle("Statistiken von " + discordPlayerStats.getMinecraftName()) - .setDescription("**Role**: " + discordPlayerStats.getRole()) + .setTitle("Statistiken von " + connectionDataValue.getMinecraftName()) + .setDescription("**Role**: " + connectionDataValue.getRole()) .setFooter(member.getEffectiveName(), member.getEffectiveAvatarUrl()) .setTimestamp(new Date().toInstant()); } - private String getCharacteristics(DiscordPlayerStats discordPlayerStats) { + private String getCharacteristics(ConnectionDataValue connectionDataValue) { return """ **Name**: %s **Alter**: %s **Geschlecht**: %s """ - .formatted(discordPlayerStats.getRoleplayName(), - discordPlayerStats.getAge(), - discordPlayerStats.getGender().equals("MAN") ? ":male_sign:" : ":female_sign:"); + .formatted(connectionDataValue.getRoleplayName(), + connectionDataValue.getAge(), + connectionDataValue.getGender().equals("MAN") ? ":male_sign:" : ":female_sign:"); } - private String getBalances(DiscordPlayerStats discordPlayerStats) { + private String getBalances(ConnectionDataValue connectionDataValue) { return """ **Bank**: %s$ **Bargeld**: %s$ **PayPal**: %s$ """ - .formatted(DECIMAL_FORMAT.format(discordPlayerStats.getBankBalance()), DECIMAL_FORMAT.format(discordPlayerStats.getCashBalance()), DECIMAL_FORMAT.format(discordPlayerStats.getPalPayBalance())); + .formatted(DECIMAL_FORMAT.format(connectionDataValue.getBankBalance()), DECIMAL_FORMAT.format(connectionDataValue.getCashBalance()), DECIMAL_FORMAT.format(connectionDataValue.getPalPayBalance())); } private String getPunishments(PunishmentData punishmentData) { @@ -139,7 +139,7 @@ private String getPunishments(PunishmentData punishmentData) { .formatted(!punishmentData.noWeaponBlockActive(), !punishmentData.noGroupBlockActive(), !punishmentData.noSkillBlockActive(), !punishmentData.noAdBlockActive(), !punishmentData.noCarBlockActive(), punishmentData.getCheckpointsLeft()); } - private String getHouses(List houses) { + private String getHouses(List houses) { StringJoiner houseJoiner = new StringJoiner("\n- ", "- ", ""); houses.stream() .map(Object::toString) diff --git a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java index 1277fda..2c700a7 100644 --- a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java @@ -4,10 +4,10 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.turniptales.discord.common.api.Api; -import net.turniptales.discord.common.api.model.DiscordPlayerStats; +import net.turniptales.discord.common.api.model.ConnectionDataValue; +import org.springframework.http.ResponseEntity; import static java.util.Objects.isNull; -import static java.util.Objects.nonNull; import static java.util.concurrent.TimeUnit.SECONDS; public class VerifyCommand extends ListenerAdapter { @@ -24,10 +24,16 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { return; } - DiscordPlayerStats discordPlayerStats = new Api().getPlayerStatsByDiscordUserId(e.getUser().getIdLong(), codeOptionMapping.getAsString()); + Api api = new Api(); + + long accountUserId = e.getUser().getIdLong(); + ResponseEntity response = api.connect(accountUserId, codeOptionMapping.getAsString()); + boolean success = response.getStatusCode().is2xxSuccessful(); + String message; - if (nonNull(discordPlayerStats)) { - message = "Du hast deinen Discord Account mit dem Minecraft Account " + discordPlayerStats.getMinecraftName() + " verknüpft!\nDiese Nachricht zerstört sich gleich von selbst..."; + if (success) { + ConnectionDataValue connectionDataValue = api.getData(accountUserId); + message = "Du hast deinen Discord Account mit dem Minecraft Account " + connectionDataValue.getMinecraftName() + " verknüpft!"; } else { message = "Dein Discord Account konnte nicht mit deinem Minecraft Account verknüpft werden."; } diff --git a/src/main/java/net/turniptales/discord/common/api/Api.java b/src/main/java/net/turniptales/discord/common/api/Api.java index fbab20b..e1473c9 100644 --- a/src/main/java/net/turniptales/discord/common/api/Api.java +++ b/src/main/java/net/turniptales/discord/common/api/Api.java @@ -7,40 +7,38 @@ import com.google.gson.JsonSerializer; import lombok.Data; import lombok.extern.log4j.Log4j2; -import net.turniptales.discord.common.api.model.DiscordPlayerStats; -import org.jetbrains.annotations.Nullable; +import net.turniptales.discord.common.api.model.ConnectionDataValue; +import org.springframework.http.ResponseEntity; import org.springframework.web.reactive.function.client.WebClient; import java.time.ZonedDateTime; +import static java.lang.String.format; import static java.time.ZonedDateTime.parse; import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME; -import static java.util.Optional.ofNullable; import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.POST; @Log4j2 @Data public class Api { /** - * {@link DiscordPlayerStats} + * {@link ConnectionDataValue} */ - public DiscordPlayerStats getPlayerStatsByDiscordUserId(long userId, @Nullable String discordCode) { - String code = ofNullable(discordCode) - .map(c -> "?discordCode=" + c) - .orElse(""); + public ConnectionDataValue getData(long accountUserId) { + String url = format("/data?discordUserId%s", accountUserId); + return getGson().fromJson(sendGetRequest(url), ConnectionDataValue.class); + } - return parseGetRequest("/" + userId + code, DiscordPlayerStats.class); + public ResponseEntity connect(long accountUserId, String code) { + String url = format("/connect?type=DISCORD&accountUserId=%s&code=%s", accountUserId, code); + return sendPostRequest(url); } /** * Request */ - private T parseGetRequest(String url, Class model) { - Gson gson = getGson(); - return gson.fromJson(sendGetRequest(url), model); - } - private Gson getGson() { return new GsonBuilder() .registerTypeAdapter(ZonedDateTime.class, (JsonDeserializer) (json, type, jsonDeserializationContext) -> parse(json.getAsJsonPrimitive().getAsString())) @@ -55,9 +53,16 @@ private String sendGetRequest(String url) { .block(); } + private ResponseEntity sendPostRequest(String url) { + return getClient(url).method(POST) + .retrieve() + .toBodilessEntity() + .block(); + } + private WebClient getClient(String url) { return WebClient.builder() - .baseUrl("https://turniptales.net:7200/turniptalesapi/v1/verification/discord" + url) + .baseUrl("https://turniptales.net:7200/turniptalesapi/v1/connection" + url) .defaultHeader("Authorization", "Basic dHVybmlwdGFsZXMtYXBpdXNlcjoqYnp0OThjV3EvLCckOT41SEN7NlEtTycralZFZmprMQ==") .build(); } diff --git a/src/main/java/net/turniptales/discord/common/api/model/DiscordPlayerStats.java b/src/main/java/net/turniptales/discord/common/api/model/ConnectionDataValue.java similarity index 71% rename from src/main/java/net/turniptales/discord/common/api/model/DiscordPlayerStats.java rename to src/main/java/net/turniptales/discord/common/api/model/ConnectionDataValue.java index 5f3dedc..8bd574e 100644 --- a/src/main/java/net/turniptales/discord/common/api/model/DiscordPlayerStats.java +++ b/src/main/java/net/turniptales/discord/common/api/model/ConnectionDataValue.java @@ -8,15 +8,21 @@ @Data @Builder -public class DiscordPlayerStats { +public class ConnectionDataValue { // data + private String citizenId; private UUID minecraftUuid; private String minecraftName; private String role; + private String roleDisplayName; + private List teams; private int level; - private String group; private int knownPlayerCount; + // group + private String group; + private int factionRank; + private boolean leaderRights; // characteristics private String roleplayName; private int age; @@ -25,7 +31,8 @@ public class DiscordPlayerStats { private double bankBalance; private double cashBalance; private double palPayBalance; + // other private PunishmentData punishmentData; - private List houses; + private List houses; private List cars; } diff --git a/src/main/java/net/turniptales/discord/common/api/model/PunishmentData.java b/src/main/java/net/turniptales/discord/common/api/model/PunishmentData.java index 02df01d..d054aa2 100644 --- a/src/main/java/net/turniptales/discord/common/api/model/PunishmentData.java +++ b/src/main/java/net/turniptales/discord/common/api/model/PunishmentData.java @@ -15,7 +15,6 @@ @Builder public class PunishmentData { - private long id; @Nullable private ZonedDateTime weaponBlockUntilDateTime; @Nullable From 1f8d024cb3d7d93e0cf4d570de0329a7e2af0076 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 17:23:44 +0000 Subject: [PATCH 26/58] Update dependency org.apache.tomcat.embed:tomcat-embed-core to v10.1.25 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e9a4976..62aa604 100644 --- a/pom.xml +++ b/pom.xml @@ -40,7 +40,7 @@ org.apache.tomcat.embed tomcat-embed-core - 10.1.19 + 10.1.25 From 5a0c48d7db8e92e0a6695b5d78256565cd8c0721 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 17:27:59 +0000 Subject: [PATCH 27/58] Update dependency net.dv8tion:JDA to v5.0.0-beta.24 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 62aa604..60ecb4c 100644 --- a/pom.xml +++ b/pom.xml @@ -54,7 +54,7 @@ net.dv8tion JDA - 5.0.0-alpha.21 + 5.0.0-beta.24 From 1b53f7558d49b5aa7e648a9daa7326b6bc25d425 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 3 Jul 2024 19:30:38 +0200 Subject: [PATCH 28/58] Resolve dependency conflicts --- .../turniptales/discord/events/ButtonInteractionListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java index 25cfef0..cbe3f0f 100644 --- a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java +++ b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java @@ -7,9 +7,9 @@ import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.components.ActionRow; -import net.dv8tion.jda.api.interactions.components.Modal; import net.dv8tion.jda.api.interactions.components.text.TextInput; import net.dv8tion.jda.api.interactions.components.text.TextInputStyle; +import net.dv8tion.jda.api.interactions.modals.Modal; import net.turniptales.discord.Config; import java.util.EnumSet; @@ -19,11 +19,11 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static net.dv8tion.jda.api.Permission.VIEW_CHANNEL; import static net.dv8tion.jda.api.entities.emoji.Emoji.fromUnicode; -import static net.dv8tion.jda.api.interactions.components.Modal.create; import static net.dv8tion.jda.api.interactions.components.buttons.Button.danger; import static net.dv8tion.jda.api.interactions.components.buttons.Button.secondary; import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; import static net.dv8tion.jda.api.interactions.components.text.TextInputStyle.PARAGRAPH; +import static net.dv8tion.jda.api.interactions.modals.Modal.create; import static net.turniptales.discord.Config.GUILD; import static net.turniptales.discord.Config.MODERATOR_ROLE; import static net.turniptales.discord.Config.SENIOR_MODERATOR_ROLE; From f27103f2d4a16e2e4c6c4133710ded746bb1856f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:42:31 +0000 Subject: [PATCH 29/58] Update dependency com.google.code.gson:gson to v2.11.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 60ecb4c..1d5fb0f 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ com.google.code.gson gson - 2.10.1 + 2.11.0 From a857cfabff0611479d8ca167a6ad63e6ecc8abc6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:42:35 +0000 Subject: [PATCH 30/58] Update dependency maven to v3.9.8 --- .mvn/wrapper/maven-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index b7cb93e..caed2c5 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,2 +1,2 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.8/apache-maven-3.9.8-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar From 7efacf5fd695ae9b7c5c06987587c98242051a18 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 22:19:38 +0000 Subject: [PATCH 31/58] Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 60ecb4c..fdada11 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 3.1.4 + 3.3.1 From 08ea90e8a443cd184cfe15637784d1db37adf502 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 22:21:29 +0000 Subject: [PATCH 32/58] Update dependency maven-wrapper to v3.3.2 --- .mvn/wrapper/maven-wrapper.properties | 19 +- mvnw | 459 +++++++++++--------------- mvnw.cmd | 337 +++++++++---------- 3 files changed, 368 insertions(+), 447 deletions(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index caed2c5..f95f1ee 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,2 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.8/apache-maven-3.9.8-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/mvnw b/mvnw index 8a8fb22..19529dd 100644 --- a/mvnw +++ b/mvnw @@ -8,7 +8,7 @@ # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an @@ -19,298 +19,241 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir +# Apache Maven Wrapper startup batch script, version 3.3.2 # # Optional ENV vars # ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output # ---------------------------------------------------------------------------- -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /usr/local/etc/mavenrc ] ; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac -fi +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 fi fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" +} - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" done + printf %x\\n $h +} - saveddir=`pwd` +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - M2_HOME=`dirname "$PRG"`/.. +die() { + printf %s\\n "$1" >&2 + exit 1 +} - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" fi -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`\\unset -f command; \\command -v java`" - fi +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" fi -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi +mkdir -p -- "${MAVEN_HOME%/*}" -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" fi -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; fi -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd index 1d8ab01..b150b91 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -1,188 +1,149 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" From 1bffa5c64afb13d85a72f5f5a9a05e219bf1c81d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jul 2024 01:24:47 +0000 Subject: [PATCH 33/58] Update actions/checkout action to v4 --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6783f77..c4e0d17 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v3 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bc63217..5ccc845 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v3 with: From 6ec5fce914931ed7635ef0d20bb8cb31b100afef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jul 2024 01:24:50 +0000 Subject: [PATCH 34/58] Update actions/setup-java action to v4 --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6783f77..5575674 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'corretto' java-version: '17' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bc63217..7ddfb97 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'corretto' java-version: '17' From 6fe5fa69d15e97e84a93c41e23777c3bbaf74f14 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jul 2024 05:05:16 +0000 Subject: [PATCH 35/58] Update actions/upload-artifact action to v4 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bc63217..9ec42c8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: - name: Build with Maven run: mvn -B package --file pom.xml - name: Upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Artifacts path: target/turniptales-discord.jar \ No newline at end of file From 538e54e71885f4cdf629cd126a10a21858d90c53 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jul 2024 05:05:19 +0000 Subject: [PATCH 36/58] Update openjdk Docker tag to v24 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a318fe7..a901423 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:17 +FROM openjdk:24 WORKDIR /app From 6a9452bbc9883c9b02e3987ccc28c1b8c7b3c3e9 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 5 Jul 2024 16:59:40 +0200 Subject: [PATCH 37/58] Reformat code --- .../java/net/turniptales/discord/commands/GiveawayCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java b/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java index 334d343..85c20cc 100644 --- a/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java +++ b/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java @@ -87,6 +87,7 @@ public List getUsersWhoReacted(List reactions) { } public static class Giveaway { + private final Message message; private final List users; private final User winner; From deae06ed8ad1e077ba3ed320d2f42381a2d28352 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 5 Jul 2024 17:02:51 +0200 Subject: [PATCH 38/58] Add static api instance in TurnipTalesDiscord --- .../java/net/turniptales/discord/Config.java | 4 ++-- .../discord/TurnipTalesDiscord.java | 21 +++++++++++-------- .../discord/commands/StatsCommand.java | 3 +-- .../discord/commands/VerifyCommand.java | 2 +- .../common/services/ActivitySyncService.java | 4 ++-- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/turniptales/discord/Config.java b/src/main/java/net/turniptales/discord/Config.java index e664b36..04f5dc5 100644 --- a/src/main/java/net/turniptales/discord/Config.java +++ b/src/main/java/net/turniptales/discord/Config.java @@ -6,11 +6,11 @@ import net.dv8tion.jda.api.entities.channel.concrete.Category; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import static net.turniptales.discord.TurnipTalesDiscord.TURNIPTALES_BOT; +import static net.turniptales.discord.TurnipTalesDiscord.turniptalesBot; public class Config { - public static final Guild GUILD = TURNIPTALES_BOT.getGuildById("1008928645185810463"); + public static final Guild GUILD = turniptalesBot.getGuildById("1008928645185810463"); public static final Member BOT; // channels public static final TextChannel COMMUNITY_TEXT_CHANNEL = GUILD.getTextChannelById("1008929885764472952"); diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index 58814b7..20ab60d 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -8,6 +8,7 @@ import net.turniptales.discord.commands.SurveyCommand; import net.turniptales.discord.commands.TicketCommand; import net.turniptales.discord.commands.VerifyCommand; +import net.turniptales.discord.common.api.Api; import net.turniptales.discord.events.ButtonInteractionListener; import net.turniptales.discord.events.GuildMemberJoinListener; import net.turniptales.discord.events.GuildMemberRemoveListener; @@ -33,21 +34,23 @@ @SpringBootApplication public class TurnipTalesDiscord implements WebMvcConfigurer { - public static JDA TURNIPTALES_BOT; - public static ZoneId ZONE_ID; + public static final ZoneId ZONE_ID = of("Europe/Berlin"); + public static JDA turniptalesBot; + public static Api api; public static void main(String[] args) { SpringApplication.run(TurnipTalesDiscord.class, args); - ZONE_ID = of("Europe/Berlin"); long discordBotStartTime = currentTimeMillis(); log.info("Discord bot starting"); startDiscordBot(); log.info("Discord bot started in {}ms", currentTimeMillis() - discordBotStartTime); + + api = new Api(); } private static void startDiscordBot() { - TURNIPTALES_BOT = JDABuilder + turniptalesBot = JDABuilder .createDefault("MTE5MDcxNDY0MzU1MTg5MTQ3OA.GdvTJE.EMI9oOxjzEe-unfAXWPtOKgb2qGtWkqonPq5OY") .disableCache(MEMBER_OVERRIDES, VOICE_STATE) // Disable parts of the cache .setBulkDeleteSplittingEnabled(false) // Enable the bulk delete event @@ -70,12 +73,12 @@ private static void startDiscordBot() { ) .build(); - TURNIPTALES_BOT + turniptalesBot .upsertCommand("stats", "Deine Statistiken (nicht öffentlich) oder die eines Discord Nutzers (öffentlich)") .addOption(USER, "player", "Discord Nutzer dessen Statistiken angezeigt werden sollen (Discord Nutzer muss sich verknüpft haben)", false) .queue(); - TURNIPTALES_BOT + turniptalesBot .upsertCommand("umfrage", "Erstellt eine Umfrage") .addOption(STRING, "question", "Frage", true) .addOption(STRING, "description", "Beschreibung", true) @@ -86,16 +89,16 @@ private static void startDiscordBot() { .addOption(STRING, "answer5", "Antwort 5", false) .queue(); - TURNIPTALES_BOT + turniptalesBot .upsertCommand("ticket", "Erstellt die Nachricht um Tickets zu erstellen") .queue(); - TURNIPTALES_BOT + turniptalesBot .upsertCommand("verify", "Verifiziert deinen Minecraft Account") .addOption(STRING, "code", "Verifizierungscode", true) .queue(); - TURNIPTALES_BOT + turniptalesBot .upsertCommand("giveaway", "Lost einen Spieler anhand der Reaktionen einer Nachricht aus") .addOption(STRING, "message", "Nachricht mit den Reaktionen", true) .queue(); diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index 8e0dfd5..f75871e 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -8,7 +8,6 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; -import net.turniptales.discord.common.api.Api; import net.turniptales.discord.common.api.model.ConnectionDataValue; import net.turniptales.discord.common.api.model.PunishmentData; @@ -24,6 +23,7 @@ import static java.util.Objects.nonNull; import static java.util.concurrent.TimeUnit.SECONDS; import static net.turniptales.discord.Config.BOT; +import static net.turniptales.discord.TurnipTalesDiscord.api; public class StatsCommand extends ListenerAdapter { @@ -38,7 +38,6 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { OptionMapping playerOptionMapping = e.getOption("player"); - Api api = new Api(); Member member = e.getMember(); if (nonNull(playerOptionMapping)) { try { diff --git a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java index 2c700a7..41f3508 100644 --- a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java @@ -3,12 +3,12 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; -import net.turniptales.discord.common.api.Api; import net.turniptales.discord.common.api.model.ConnectionDataValue; import org.springframework.http.ResponseEntity; import static java.util.Objects.isNull; import static java.util.concurrent.TimeUnit.SECONDS; +import static net.turniptales.discord.TurnipTalesDiscord.api; public class VerifyCommand extends ListenerAdapter { diff --git a/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java b/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java index b82de04..b290ad8 100644 --- a/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java +++ b/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java @@ -10,7 +10,7 @@ import static java.lang.System.currentTimeMillis; import static java.util.concurrent.TimeUnit.MINUTES; import static net.dv8tion.jda.api.entities.Activity.playing; -import static net.turniptales.discord.TurnipTalesDiscord.TURNIPTALES_BOT; +import static net.turniptales.discord.TurnipTalesDiscord.turniptalesBot; @Log4j2 @Component @@ -26,7 +26,7 @@ public void run() { log.info("Activity synchronising: started"); Activity activity = playing("auf TurnipTales.net"); - TURNIPTALES_BOT.getPresence().setActivity(activity); + turniptalesBot.getPresence().setActivity(activity); log.info("Activity synchronising: finished in {}ms", currentTimeMillis() - startTime); } From cbf04f9d54c2c65c34acf3cfd87504ecb66f8164 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 5 Jul 2024 17:04:19 +0200 Subject: [PATCH 39/58] Update id from long to string in api request --- .../java/net/turniptales/discord/commands/StatsCommand.java | 4 ++-- .../java/net/turniptales/discord/commands/VerifyCommand.java | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index f75871e..2c21ae6 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -41,7 +41,7 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { Member member = e.getMember(); if (nonNull(playerOptionMapping)) { try { - ConnectionDataValue connectionDataValue = api.getData(e.getUser().getIdLong()); + ConnectionDataValue connectionDataValue = api.getData(e.getUser().getId()); MessageEmbed publicPlayerStats = isTicketChannel(e.getChannel()) ? getPrivatePlayerStats(connectionDataValue, member) : getPublicPlayerStats(connectionDataValue, member); e.replyEmbeds(publicPlayerStats).queue(); } catch (Exception ex) { @@ -50,7 +50,7 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { } } else { try { - ConnectionDataValue connectionDataValue = api.getData(e.getUser().getIdLong()); + ConnectionDataValue connectionDataValue = api.getData(e.getUser().getId()); MessageEmbed privatePlayerStats = getPrivatePlayerStats(connectionDataValue, member); e.replyEmbeds(privatePlayerStats).setEphemeral(true).queue(); } catch (Exception ex) { diff --git a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java index 41f3508..2464fe0 100644 --- a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java @@ -24,10 +24,8 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { return; } - Api api = new Api(); - - long accountUserId = e.getUser().getIdLong(); ResponseEntity response = api.connect(accountUserId, codeOptionMapping.getAsString()); + String accountUserId = e.getUser().getId(); boolean success = response.getStatusCode().is2xxSuccessful(); String message; From c48ea3558dd8ae1757599a36e02883c42b136a9b Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 5 Jul 2024 17:05:48 +0200 Subject: [PATCH 40/58] Update api handling --- .../discord/commands/VerifyCommand.java | 2 +- .../turniptales/discord/common/api/Api.java | 32 +++++++++++-------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java index 2464fe0..3cac80b 100644 --- a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java @@ -24,8 +24,8 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { return; } - ResponseEntity response = api.connect(accountUserId, codeOptionMapping.getAsString()); String accountUserId = e.getUser().getId(); + ResponseEntity response = api.connect(accountUserId, codeOptionMapping.getAsString()); boolean success = response.getStatusCode().is2xxSuccessful(); String message; diff --git a/src/main/java/net/turniptales/discord/common/api/Api.java b/src/main/java/net/turniptales/discord/common/api/Api.java index e1473c9..19271cf 100644 --- a/src/main/java/net/turniptales/discord/common/api/Api.java +++ b/src/main/java/net/turniptales/discord/common/api/Api.java @@ -8,11 +8,15 @@ import lombok.Data; import lombok.extern.log4j.Log4j2; import net.turniptales.discord.common.api.model.ConnectionDataValue; +import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import reactor.core.publisher.Mono; import java.time.ZonedDateTime; +import static com.google.gson.JsonParser.parseString; import static java.lang.String.format; import static java.time.ZonedDateTime.parse; import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME; @@ -26,14 +30,14 @@ public class Api { /** * {@link ConnectionDataValue} */ - public ConnectionDataValue getData(long accountUserId) { - String url = format("/data?discordUserId%s", accountUserId); - return getGson().fromJson(sendGetRequest(url), ConnectionDataValue.class); + public ConnectionDataValue getData(String accountUserId) { + String url = format("/data?discordUserId=%s", accountUserId); + return getGson().fromJson(sendRequest(url, GET).getBody(), ConnectionDataValue.class); } - public ResponseEntity connect(long accountUserId, String code) { + public ResponseEntity connect(String accountUserId, String code) { String url = format("/connect?type=DISCORD&accountUserId=%s&code=%s", accountUserId, code); - return sendPostRequest(url); + return sendRequest(url, POST); } /** @@ -46,17 +50,17 @@ private Gson getGson() { .create(); } - private String sendGetRequest(String url) { - return getClient(url).method(GET) + private ResponseEntity sendRequest(String url, HttpMethod method) { + return getClient(url).method(method) .retrieve() .bodyToMono(String.class) - .block(); - } - - private ResponseEntity sendPostRequest(String url) { - return getClient(url).method(POST) - .retrieve() - .toBodilessEntity() + .map(ResponseEntity::ok) + .onErrorResume(WebClientResponseException.class, ex -> { + String responseBodyAsString = ex.getResponseBodyAsString(); + String info = parseString(responseBodyAsString).getAsJsonObject().get("info").getAsString(); + log.error("Request failed with code {}: {}", ex.getStatusCode(), info); + return Mono.just(ResponseEntity.status(ex.getStatusCode()).body(responseBodyAsString)); + }) .block(); } From edd9ee77c611d1693b9cca30034d2475cc457da2 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Sat, 6 Jul 2024 14:28:10 +0200 Subject: [PATCH 41/58] Sync application with teamspeak application --- pom.xml | 9 +++------ src/main/java/net/turniptales/discord/Config.java | 4 ++-- .../turniptales/discord/TurnipTalesDiscord.java | 14 +++++++------- .../common/services/ActivitySyncService.java | 4 ++-- src/main/resources/application.properties | 4 +++- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index d40bc20..eb900c4 100644 --- a/pom.xml +++ b/pom.xml @@ -37,12 +37,6 @@ spring-boot-starter-webflux - - org.apache.tomcat.embed - tomcat-embed-core - 10.1.25 - - com.google.code.gson @@ -70,9 +64,12 @@ 1.1.1 + org.projectlombok lombok + 1.18.34 + provided true diff --git a/src/main/java/net/turniptales/discord/Config.java b/src/main/java/net/turniptales/discord/Config.java index 04f5dc5..8b1eba3 100644 --- a/src/main/java/net/turniptales/discord/Config.java +++ b/src/main/java/net/turniptales/discord/Config.java @@ -6,11 +6,11 @@ import net.dv8tion.jda.api.entities.channel.concrete.Category; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import static net.turniptales.discord.TurnipTalesDiscord.turniptalesBot; +import static net.turniptales.discord.TurnipTalesDiscord.discordBot; public class Config { - public static final Guild GUILD = turniptalesBot.getGuildById("1008928645185810463"); + public static final Guild GUILD = discordBot.getGuildById("1008928645185810463"); public static final Member BOT; // channels public static final TextChannel COMMUNITY_TEXT_CHANNEL = GUILD.getTextChannelById("1008929885764472952"); diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index 20ab60d..89b3929 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -35,7 +35,7 @@ public class TurnipTalesDiscord implements WebMvcConfigurer { public static final ZoneId ZONE_ID = of("Europe/Berlin"); - public static JDA turniptalesBot; + public static JDA discordBot; public static Api api; public static void main(String[] args) { @@ -50,7 +50,7 @@ public static void main(String[] args) { } private static void startDiscordBot() { - turniptalesBot = JDABuilder + discordBot = JDABuilder .createDefault("MTE5MDcxNDY0MzU1MTg5MTQ3OA.GdvTJE.EMI9oOxjzEe-unfAXWPtOKgb2qGtWkqonPq5OY") .disableCache(MEMBER_OVERRIDES, VOICE_STATE) // Disable parts of the cache .setBulkDeleteSplittingEnabled(false) // Enable the bulk delete event @@ -73,12 +73,12 @@ private static void startDiscordBot() { ) .build(); - turniptalesBot + discordBot .upsertCommand("stats", "Deine Statistiken (nicht öffentlich) oder die eines Discord Nutzers (öffentlich)") .addOption(USER, "player", "Discord Nutzer dessen Statistiken angezeigt werden sollen (Discord Nutzer muss sich verknüpft haben)", false) .queue(); - turniptalesBot + discordBot .upsertCommand("umfrage", "Erstellt eine Umfrage") .addOption(STRING, "question", "Frage", true) .addOption(STRING, "description", "Beschreibung", true) @@ -89,16 +89,16 @@ private static void startDiscordBot() { .addOption(STRING, "answer5", "Antwort 5", false) .queue(); - turniptalesBot + discordBot .upsertCommand("ticket", "Erstellt die Nachricht um Tickets zu erstellen") .queue(); - turniptalesBot + discordBot .upsertCommand("verify", "Verifiziert deinen Minecraft Account") .addOption(STRING, "code", "Verifizierungscode", true) .queue(); - turniptalesBot + discordBot .upsertCommand("giveaway", "Lost einen Spieler anhand der Reaktionen einer Nachricht aus") .addOption(STRING, "message", "Nachricht mit den Reaktionen", true) .queue(); diff --git a/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java b/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java index b290ad8..cfe9b7b 100644 --- a/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java +++ b/src/main/java/net/turniptales/discord/common/services/ActivitySyncService.java @@ -10,7 +10,7 @@ import static java.lang.System.currentTimeMillis; import static java.util.concurrent.TimeUnit.MINUTES; import static net.dv8tion.jda.api.entities.Activity.playing; -import static net.turniptales.discord.TurnipTalesDiscord.turniptalesBot; +import static net.turniptales.discord.TurnipTalesDiscord.discordBot; @Log4j2 @Component @@ -26,7 +26,7 @@ public void run() { log.info("Activity synchronising: started"); Activity activity = playing("auf TurnipTales.net"); - turniptalesBot.getPresence().setActivity(activity); + discordBot.getPresence().setActivity(activity); log.info("Activity synchronising: finished in {}ms", currentTimeMillis() - startTime); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 354888b..a0b96f3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,7 @@ server.port=9000 + server.error.path=/error server.error.whitelabel.enabled=false + spring.main.banner-mode=off -spring.output.ansi.enabled=ALWAYS \ No newline at end of file +spring.output.ansi.enabled=ALWAYS From 20cafe2d0db2fd3f98cfca92f248416f02cbd6de Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 7 Jul 2024 20:32:04 +0000 Subject: [PATCH 42/58] Update dependency net.dv8tion:JDA to v5.0.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eb900c4..a35f51b 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ net.dv8tion JDA - 5.0.0-beta.24 + 5.0.0 From 848636b42bf31e8a0a9a910872ef4e36ac5caed1 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Sun, 14 Jul 2024 23:20:27 +0200 Subject: [PATCH 43/58] Remove deprecated method call --- .../turniptales/discord/events/ButtonInteractionListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java index cbe3f0f..dda6863 100644 --- a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java +++ b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java @@ -72,7 +72,7 @@ public void onButtonInteraction(ButtonInteractionEvent e) { .build(); Modal ticketModal = create("ticket_modal", "Neues Ticket") - .addActionRows(ActionRow.of(minecraftNameTextInput), ActionRow.of(logInput)) + .addComponents(ActionRow.of(minecraftNameTextInput), ActionRow.of(logInput)) .build(); e.replyModal(ticketModal).queue(); From bca88cf9494c182383ab6b226fc81f16d0809d3c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 18:23:52 +0000 Subject: [PATCH 44/58] Update dependency net.dv8tion:JDA to v5.0.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a35f51b..108d10b 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ net.dv8tion JDA - 5.0.0 + 5.0.1 From a8b27590a4698b899c15c42258fe31aba9602213 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 00:16:00 +0200 Subject: [PATCH 45/58] Migrate GuildMemberJoinListener and GuildMemberRemoveListener into GuildAccessListener and add discord bot config --- .../java/net/turniptales/discord/Config.java | 41 ----- .../discord/TurnipTalesDiscord.java | 9 +- .../configuration/DiscordBotProperties.java | 145 ++++++++++++++++++ .../common/services/RoleSyncService.java | 65 ++++---- .../events/ButtonInteractionListener.java | 43 ++---- ...Listener.java => GuildAccessListener.java} | 52 +++++-- .../events/GuildMemberJoinListener.java | 51 ------ .../GuildMemberUpdateBoostTimeListener.java | 37 ----- .../events/MessageReactionListener.java | 4 +- src/main/resources/application.properties | 24 +++ 10 files changed, 266 insertions(+), 205 deletions(-) delete mode 100644 src/main/java/net/turniptales/discord/Config.java create mode 100644 src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java rename src/main/java/net/turniptales/discord/events/{GuildMemberRemoveListener.java => GuildAccessListener.java} (51%) delete mode 100644 src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java delete mode 100644 src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java diff --git a/src/main/java/net/turniptales/discord/Config.java b/src/main/java/net/turniptales/discord/Config.java deleted file mode 100644 index 8b1eba3..0000000 --- a/src/main/java/net/turniptales/discord/Config.java +++ /dev/null @@ -1,41 +0,0 @@ -package net.turniptales.discord; - -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.Role; -import net.dv8tion.jda.api.entities.channel.concrete.Category; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; - -import static net.turniptales.discord.TurnipTalesDiscord.discordBot; - -public class Config { - - public static final Guild GUILD = discordBot.getGuildById("1008928645185810463"); - public static final Member BOT; - // channels - public static final TextChannel COMMUNITY_TEXT_CHANNEL = GUILD.getTextChannelById("1008929885764472952"); - public static final TextChannel SURVEY_TEXT_CHANNEL = GUILD.getTextChannelById("1206336710128959519"); - public static final TextChannel TICKET_TEXT_CHANNEL = GUILD.getTextChannelById("1009477703990267954"); - // - public static final Category TICKET_CATEGORY = GUILD.getCategoryById("1009478372847517727"); - // player roles - public static final Role PLAYER_ROLE = GUILD.getRoleById("1190675464549847110"); - // team roles - public static final Role SENIOR_MODERATOR_ROLE = GUILD.getRoleById("1208149723547050004"); - public static final Role MODERATOR_ROLE = GUILD.getRoleById("1025864289346658355"); - public static final Role SUPPORTER_ROLE = GUILD.getRoleById("1009477020427747408"); - // user time roles - public static final Role ROLE_0 = GUILD.getRoleById("1134487019058372649"); - public static final Role ROLE_1_WEEK = GUILD.getRoleById("1134487221349650462"); - public static final Role ROLE_2_WEEK = GUILD.getRoleById("1134487277205192744"); - public static final Role ROLE_1_MONTH = GUILD.getRoleById("1134487413125820477"); - public static final Role ROLE_3_MONTH = GUILD.getRoleById("1134487461452583043"); - public static final Role ROLE_6_MONTH = GUILD.getRoleById("1134487539588268094"); - public static final Role ROLE_1_YEAR = GUILD.getRoleById("1134487593585745920"); - public static final Role ROLE_2_YEAR = GUILD.getRoleById("1134487644110336010"); - public static final Role ROLE_3_YEAR = GUILD.getRoleById("1134487702864142356"); - - static { - BOT = GUILD.getMemberById("1190714643551891478"); - } -} diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index 89b3929..54c2e1a 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -9,6 +9,7 @@ import net.turniptales.discord.commands.TicketCommand; import net.turniptales.discord.commands.VerifyCommand; import net.turniptales.discord.common.api.Api; +import net.turniptales.discord.common.configuration.DiscordBotProperties; import net.turniptales.discord.events.ButtonInteractionListener; import net.turniptales.discord.events.GuildMemberJoinListener; import net.turniptales.discord.events.GuildMemberRemoveListener; @@ -16,6 +17,7 @@ import net.turniptales.discord.events.MessageReactionListener; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.time.ZoneId; @@ -36,10 +38,13 @@ public class TurnipTalesDiscord implements WebMvcConfigurer { public static final ZoneId ZONE_ID = of("Europe/Berlin"); public static JDA discordBot; + public static DiscordBotProperties discordBotProperties; public static Api api; public static void main(String[] args) { - SpringApplication.run(TurnipTalesDiscord.class, args); + ConfigurableApplicationContext context = SpringApplication.run(TurnipTalesDiscord.class, args); + + discordBotProperties = context.getBean(DiscordBotProperties.class); long discordBotStartTime = currentTimeMillis(); log.info("Discord bot starting"); @@ -51,7 +56,7 @@ public static void main(String[] args) { private static void startDiscordBot() { discordBot = JDABuilder - .createDefault("MTE5MDcxNDY0MzU1MTg5MTQ3OA.GdvTJE.EMI9oOxjzEe-unfAXWPtOKgb2qGtWkqonPq5OY") + .createDefault(discordBotProperties.getToken()) .disableCache(MEMBER_OVERRIDES, VOICE_STATE) // Disable parts of the cache .setBulkDeleteSplittingEnabled(false) // Enable the bulk delete event .setCompression(NONE) // Disable compression (not recommended) diff --git a/src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java b/src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java new file mode 100644 index 0000000..56b0a85 --- /dev/null +++ b/src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java @@ -0,0 +1,145 @@ +package net.turniptales.discord.common.configuration; + +import lombok.Getter; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.channel.concrete.Category; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import static net.turniptales.discord.TurnipTalesDiscord.discordBot; + +@Getter +@Component +public class DiscordBotProperties { + + @Value("${discord.bot.token}") + private String token; + + @Value("${discord.guild.id}") + private String guildId; + + @Value("${discord.guild.channels.community-text-channel}") + private String communityTextChannel; + + @Value("${discord.guild.channels.survey-text-channel}") + private String surveyTextChannel; + + @Value("${discord.guild.channels.ticket-text-channel}") + private String ticketTextChannel; + + @Value("${discord.guild.categories.ticket-category}") + private String ticketCategory; + + @Value("${discord.guild.roles.player-role}") + private String playerRole; + + @Value("${discord.guild.roles.senior-moderator-role}") + private String seniorModeratorRole; + + @Value("${discord.guild.roles.moderator-role}") + private String moderatorRole; + + @Value("${discord.guild.roles.supporter-role}") + private String supporterRole; + + @Value("${discord.guild.roles.role-0}") + private String role0; + + @Value("${discord.guild.roles.role-1-week}") + private String role1Week; + + @Value("${discord.guild.roles.role-2-week}") + private String role2Week; + + @Value("${discord.guild.roles.role-1-month}") + private String role1Month; + + @Value("${discord.guild.roles.role-3-month}") + private String role3Month; + + @Value("${discord.guild.roles.role-6-month}") + private String role6Month; + + @Value("${discord.guild.roles.role-1-year}") + private String role1Year; + + @Value("${discord.guild.roles.role-2-year}") + private String role2Year; + + @Value("${discord.guild.roles.role-3-year}") + private String role3Year; + + public Guild getGuild() { + return discordBot.getGuildById(this.guildId); + } + + public TextChannel getCommunityTextChannel() { + return getGuild().getTextChannelById(this.communityTextChannel); + } + + public TextChannel getSurveyTextChannel() { + return getGuild().getTextChannelById(this.surveyTextChannel); + } + + public TextChannel getTicketTextChannel() { + return getGuild().getTextChannelById(this.ticketTextChannel); + } + + public Category getTicketCategory() { + return getGuild().getCategoryById(this.ticketCategory); + } + + public Role getPlayerRole() { + return getGuild().getRoleById(this.playerRole); + } + + public Role getSeniorModeratorRole() { + return getGuild().getRoleById(this.seniorModeratorRole); + } + + public Role getModeratorRole() { + return getGuild().getRoleById(this.moderatorRole); + } + + public Role getSupporterRole() { + return getGuild().getRoleById(this.supporterRole); + } + + public Role getRole0() { + return getGuild().getRoleById(this.role0); + } + + public Role getRole1Week() { + return getGuild().getRoleById(this.role1Week); + } + + public Role getRole2Week() { + return getGuild().getRoleById(this.role2Week); + } + + public Role getRole1Month() { + return getGuild().getRoleById(this.role1Month); + } + + public Role getRole3Month() { + return getGuild().getRoleById(this.role3Month); + } + + public Role getRole6Month() { + return getGuild().getRoleById(this.role6Month); + } + + public Role getRole1Year() { + return getGuild().getRoleById(this.role1Year); + } + + public Role getRole2Year() { + return getGuild().getRoleById(this.role2Year); + } + + public Role getRole3Year() { + return getGuild().getRoleById(this.role3Year); + } +} diff --git a/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java b/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java index 96da542..29623de 100644 --- a/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java +++ b/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java @@ -3,6 +3,7 @@ import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Role; +import net.turniptales.discord.common.configuration.DiscordBotProperties; import org.springframework.stereotype.Component; import java.time.OffsetDateTime; @@ -13,47 +14,36 @@ import static java.lang.System.currentTimeMillis; import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.HOURS; -import static net.turniptales.discord.Config.GUILD; -import static net.turniptales.discord.Config.PLAYER_ROLE; -import static net.turniptales.discord.Config.ROLE_0; -import static net.turniptales.discord.Config.ROLE_1_MONTH; -import static net.turniptales.discord.Config.ROLE_1_WEEK; -import static net.turniptales.discord.Config.ROLE_1_YEAR; -import static net.turniptales.discord.Config.ROLE_2_WEEK; -import static net.turniptales.discord.Config.ROLE_2_YEAR; -import static net.turniptales.discord.Config.ROLE_3_MONTH; -import static net.turniptales.discord.Config.ROLE_3_YEAR; -import static net.turniptales.discord.Config.ROLE_6_MONTH; @Log4j2 @Component public class RoleSyncService { + private final DiscordBotProperties discordBotProperties; private List stayRoles; - public RoleSyncService() { + public RoleSyncService(DiscordBotProperties discordBotProperties) { long sixHoursInMillis = HOURS.toMillis(6); new Timer().scheduleAtFixedRate(new TimerTask() { @Override public void run() { - assert ROLE_0 != null; - assert ROLE_1_WEEK != null; - assert ROLE_2_WEEK != null; - assert ROLE_1_MONTH != null; - assert ROLE_3_MONTH != null; - assert ROLE_6_MONTH != null; - assert ROLE_1_YEAR != null; - assert ROLE_2_YEAR != null; - assert ROLE_3_YEAR != null; - RoleSyncService.this.stayRoles = List.of(ROLE_0, ROLE_1_WEEK, ROLE_2_WEEK, ROLE_1_MONTH, ROLE_3_MONTH, ROLE_6_MONTH, ROLE_1_YEAR, ROLE_2_YEAR, ROLE_3_YEAR); + RoleSyncService.this.stayRoles = List.of( + discordBotProperties.getRole0(), + discordBotProperties.getRole1Week(), + discordBotProperties.getRole2Week(), + discordBotProperties.getRole1Month(), + discordBotProperties.getRole3Month(), + discordBotProperties.getRole6Month(), + discordBotProperties.getRole1Year(), + discordBotProperties.getRole2Year(), + discordBotProperties.getRole3Year() + ); long startTime = currentTimeMillis(); log.info("Discord role synchronising: started"); - Guild guild = GUILD; - - assert guild != null; + Guild guild = discordBotProperties.getGuild(); guild.loadMembers().get().forEach(member -> { Role highestRoleUserShouldHave = getHighestRoleUserShouldHave(member.getTimeJoined()); RoleSyncService.this.stayRoles.stream() @@ -64,9 +54,9 @@ public void run() { log.info("Discord role synchronising: Remove role {} from member {}", role.getName(), member.getEffectiveName()); }); - if (!member.getRoles().contains(PLAYER_ROLE) || !member.getRoles().contains(highestRoleUserShouldHave)) { - assert PLAYER_ROLE != null; - guild.addRoleToMember(member, PLAYER_ROLE).queue(); + Role playerRole = discordBotProperties.getPlayerRole(); + if (!member.getRoles().contains(playerRole) || !member.getRoles().contains(highestRoleUserShouldHave)) { + guild.addRoleToMember(member, playerRole).queue(); guild.addRoleToMember(member, highestRoleUserShouldHave).queue(); log.info("Discord role synchronising: Add role {} to member {}", highestRoleUserShouldHave.getName(), member.getEffectiveName()); } @@ -76,44 +66,45 @@ public void run() { } }, (sixHoursInMillis - currentTimeMillis() % sixHoursInMillis) + HOURS.toMillis(2), sixHoursInMillis); // 4 10 16 22 log.info("Discord role synchronising: scheduled"); + this.discordBotProperties = discordBotProperties; } private Role getHighestRoleUserShouldHave(OffsetDateTime timeJoined) { - Role role = ROLE_0; + Role role = discordBotProperties.getRole0(); long joinTimeInMillis = timeJoined.toInstant().toEpochMilli(); long currentTimeInMillis = currentTimeMillis(); if (joinTimeInMillis + DAYS.toMillis(7) <= currentTimeInMillis) { // 1 Woche - role = ROLE_1_WEEK; + role = discordBotProperties.getRole1Week(); } if (joinTimeInMillis + DAYS.toMillis(14) <= currentTimeInMillis) { // 2 Wochen - role = ROLE_2_WEEK; + role = discordBotProperties.getRole2Week(); } if (joinTimeInMillis + DAYS.toMillis(30) <= currentTimeInMillis) { // 1 Monat - role = ROLE_1_MONTH; + role = discordBotProperties.getRole1Month(); } if (joinTimeInMillis + DAYS.toMillis(90) <= currentTimeInMillis) { // 3 Monate - role = ROLE_3_MONTH; + role = discordBotProperties.getRole3Month(); } if (joinTimeInMillis + DAYS.toMillis(180) <= currentTimeInMillis) { // 6 Monate - role = ROLE_6_MONTH; + role = discordBotProperties.getRole6Month(); } if (joinTimeInMillis + DAYS.toMillis(365) <= currentTimeInMillis) { // 1 Jahr - role = ROLE_1_YEAR; + role = discordBotProperties.getRole1Year(); } if (joinTimeInMillis + DAYS.toMillis(730) <= currentTimeInMillis) { // 2 Jahre - role = ROLE_2_YEAR; + role = discordBotProperties.getRole2Year(); } if (joinTimeInMillis + DAYS.toMillis(1460) <= currentTimeInMillis) { // 3 Jahre - role = ROLE_3_YEAR; + role = discordBotProperties.getRole3Year(); } return role; diff --git a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java index dda6863..039e8e9 100644 --- a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java +++ b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java @@ -1,6 +1,8 @@ package net.turniptales.discord.events; import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.channel.concrete.Category; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; @@ -10,7 +12,6 @@ import net.dv8tion.jda.api.interactions.components.text.TextInput; import net.dv8tion.jda.api.interactions.components.text.TextInputStyle; import net.dv8tion.jda.api.interactions.modals.Modal; -import net.turniptales.discord.Config; import java.util.EnumSet; import java.util.Objects; @@ -24,11 +25,7 @@ import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; import static net.dv8tion.jda.api.interactions.components.text.TextInputStyle.PARAGRAPH; import static net.dv8tion.jda.api.interactions.modals.Modal.create; -import static net.turniptales.discord.Config.GUILD; -import static net.turniptales.discord.Config.MODERATOR_ROLE; -import static net.turniptales.discord.Config.SENIOR_MODERATOR_ROLE; -import static net.turniptales.discord.Config.SUPPORTER_ROLE; -import static net.turniptales.discord.Config.TICKET_CATEGORY; +import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; import static net.turniptales.discord.commands.GiveawayCommand.giveaways; import static net.turniptales.discord.commands.SurveyCommand.pendingSurveys; @@ -37,6 +34,7 @@ public class ButtonInteractionListener extends ListenerAdapter { @Override public void onButtonInteraction(ButtonInteractionEvent e) { String componentId = e.getComponentId(); + Category ticketCategory = discordBotProperties.getTicketCategory(); switch (componentId) { case "createTicketAddButton" -> { @@ -44,12 +42,8 @@ public void onButtonInteraction(ButtonInteractionEvent e) { assert member != null; String memberId = member.getId(); - assert TICKET_CATEGORY != null; - boolean hasTicketChannel = TICKET_CATEGORY.getChannels().stream() - .map(guildChannel -> { - assert GUILD != null; - return GUILD.getTextChannelById(guildChannel.getId()); - }) + boolean hasTicketChannel = ticketCategory.getChannels().stream() + .map(guildChannel -> discordBotProperties.getGuild().getTextChannelById(guildChannel.getId())) .filter(Objects::nonNull) .map(StandardGuildMessageChannel::getTopic) .filter(Objects::nonNull) @@ -79,7 +73,7 @@ public void onButtonInteraction(ButtonInteractionEvent e) { } case "closeTicket" -> { TextChannel textChannel = e.getChannel().asTextChannel(); - if (Objects.equals(textChannel.getParentCategory(), TICKET_CATEGORY) && textChannel.getName().startsWith("ticket-")) { + if (Objects.equals(textChannel.getParentCategory(), ticketCategory) && textChannel.getName().startsWith("ticket-")) { e.reply("Möchtest Du das Ticket wirklich schließen?") .addActionRow(danger("closeTicketConfirm", "Bestätigen"), secondary("closeTicketAbort", "Abbrechen")) .queue(); @@ -87,7 +81,7 @@ public void onButtonInteraction(ButtonInteractionEvent e) { } case "closeTicketConfirm" -> { TextChannel textChannel = e.getChannel().asTextChannel(); - if (Objects.equals(textChannel.getParentCategory(), TICKET_CATEGORY) && textChannel.getName().startsWith("ticket-")) { + if (Objects.equals(textChannel.getParentCategory(), ticketCategory) && textChannel.getName().startsWith("ticket-")) { textChannel.delete().queue(); } } @@ -97,8 +91,7 @@ public void onButtonInteraction(ButtonInteractionEvent e) { assert member != null; ofNullable(pendingSurveys.remove(member)).ifPresentOrElse(survey -> { - assert Config.SURVEY_TEXT_CHANNEL != null; - Config.SURVEY_TEXT_CHANNEL.sendMessage("@everyone").setEmbeds(survey.toEmbed(member)) + discordBotProperties.getSurveyTextChannel().sendMessage("@everyone").setEmbeds(survey.toEmbed(member)) .queue(message -> survey.getReactions().forEach(emoji -> message.addReaction(emoji).queue())); e.reply("Umfrage veröffentlicht!").setEphemeral(true).queue(); @@ -130,19 +123,17 @@ public void onModalInteraction(ModalInteractionEvent e) { String minecraftName = e.getValue("minecraft_name_input").getAsString(); String log = e.getValue("topic_input").getAsString(); - assert GUILD != null; - assert SENIOR_MODERATOR_ROLE != null; - assert MODERATOR_ROLE != null; - assert SUPPORTER_ROLE != null; - TICKET_CATEGORY.createTextChannel("ticket-" + userName) + Role supporterRole = discordBotProperties.getSupporterRole(); + Role moderatorRole = discordBotProperties.getModeratorRole(); + discordBotProperties.getTicketCategory().createTextChannel("ticket-" + userName) .setTopic("Ticket von " + userName + " (" + memberId + ")") - .addPermissionOverride(GUILD.getPublicRole(), null, EnumSet.of(VIEW_CHANNEL)) + .addPermissionOverride(discordBotProperties.getGuild().getPublicRole(), null, EnumSet.of(VIEW_CHANNEL)) .addPermissionOverride(member, EnumSet.of(VIEW_CHANNEL), null) - .addPermissionOverride(SENIOR_MODERATOR_ROLE, EnumSet.of(VIEW_CHANNEL), null) - .addPermissionOverride(MODERATOR_ROLE, EnumSet.of(VIEW_CHANNEL), null) - .addPermissionOverride(SUPPORTER_ROLE, EnumSet.of(VIEW_CHANNEL), null) + .addPermissionOverride(discordBotProperties.getSeniorModeratorRole(), EnumSet.of(VIEW_CHANNEL), null) + .addPermissionOverride(moderatorRole, EnumSet.of(VIEW_CHANNEL), null) + .addPermissionOverride(supporterRole, EnumSet.of(VIEW_CHANNEL), null) .queue(textChannel -> textChannel - .sendMessage("Hey " + member.getAsMention() + "! Danke dass du ein Ticket erstellt hast. Die " + SUPPORTER_ROLE.getAsMention() + " und " + MODERATOR_ROLE.getAsMention() + " werden Dir schnellstmöglich deine Frage beantworten oder Dir helfen.\n" + .sendMessage("Hey " + member.getAsMention() + "! Danke dass du ein Ticket erstellt hast. Die " + supporterRole.getAsMention() + " und " + moderatorRole.getAsMention() + " werden Dir schnellstmöglich deine Frage beantworten oder Dir helfen.\n" + "Spieler: " + minecraftName + "\n" + "Anliegen: " + log) .addActionRow(success("closeTicket", "Ticket schließen").withEmoji(fromUnicode("U+1F512"))) diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java b/src/main/java/net/turniptales/discord/events/GuildAccessListener.java similarity index 51% rename from src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java rename to src/main/java/net/turniptales/discord/events/GuildAccessListener.java index 0835e6b..1d6161a 100644 --- a/src/main/java/net/turniptales/discord/events/GuildMemberRemoveListener.java +++ b/src/main/java/net/turniptales/discord/events/GuildAccessListener.java @@ -2,32 +2,66 @@ import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.events.guild.GuildBanEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import java.awt.Color; import java.util.Date; +import static java.awt.Color.CYAN; import static java.util.Objects.nonNull; -import static net.turniptales.discord.Config.BOT; -import static net.turniptales.discord.Config.COMMUNITY_TEXT_CHANNEL; +import static net.turniptales.discord.TurnipTalesDiscord.discordBot; +import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; -public class GuildMemberRemoveListener extends ListenerAdapter { +public class GuildAccessListener extends ListenerAdapter { + + @Override + public void onGuildMemberJoin(GuildMemberJoinEvent e) { + Guild guild = e.getGuild(); + TextChannel communityTextChannel = discordBotProperties.getCommunityTextChannel(); + TextChannel missionControlTextChannel = guild.getSystemChannel(); + if (nonNull(communityTextChannel) && nonNull(missionControlTextChannel)) { + Member member = e.getMember(); + + EmbedBuilder embedBuildercommunityTextChannel = new EmbedBuilder() + .setColor(CYAN) + .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) + .setTitle("Willkommen auf TurnipTales!") + .setDescription(member.getAsMention() + " hat den Server betreten.") + .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), member.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + EmbedBuilder embedBuildermissionControlTextChannel = new EmbedBuilder() + .setColor(CYAN) + .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) + .setDescription(member.getAsMention() + " hat den Server betreten.") + .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), member.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + communityTextChannel.sendMessageEmbeds(embedBuildercommunityTextChannel.build()).queue(); + missionControlTextChannel.sendMessageEmbeds(embedBuildermissionControlTextChannel.build()).queue(); + + guild.addRoleToMember(e.getUser(), discordBotProperties.getPlayerRole()).queue(); + guild.addRoleToMember(e.getUser(), discordBotProperties.getRole0()).queue(); + } + } @Override public void onGuildBan(GuildBanEvent e) { Guild guild = e.getGuild(); - TextChannel communityTextChannel = COMMUNITY_TEXT_CHANNEL; + TextChannel communityTextChannel = discordBotProperties.getCommunityTextChannel(); TextChannel missionControlTextChannel = guild.getSystemChannel(); - if (nonNull(communityTextChannel) && nonNull(missionControlTextChannel) && nonNull(BOT)) { + if (nonNull(communityTextChannel) && nonNull(missionControlTextChannel)) { User user = e.getUser(); Color color = new Color(255, 85, 85); EmbedBuilder embedBuildercommunityTextChannel = new EmbedBuilder() .setColor(color) - .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) .setTitle("Auf wiedersehen!") .setDescription(user.getAsMention() + " nimmt sich eine Auszeit.") .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), user.getEffectiveAvatarUrl()) @@ -35,7 +69,7 @@ public void onGuildBan(GuildBanEvent e) { EmbedBuilder embedBuildermissionControlTextChannel = new EmbedBuilder() .setColor(color) - .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) .setDescription(user.getAsMention() + " wurde gebannt.") .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), user.getEffectiveAvatarUrl()) .setTimestamp(new Date().toInstant()); @@ -50,10 +84,10 @@ public void onGuildMemberRemove(GuildMemberRemoveEvent e) { Guild guild = e.getGuild(); User user = e.getUser(); TextChannel missionControlTextChannel = guild.getSystemChannel(); - if (nonNull(missionControlTextChannel) && nonNull(BOT)) { + if (nonNull(missionControlTextChannel)) { EmbedBuilder embedBuilder = new EmbedBuilder() .setColor(new Color(85, 85, 85)) - .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) .setDescription(user.getAsMention() + " hat den Server verlassen.") .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), user.getEffectiveAvatarUrl()) .setTimestamp(new Date().toInstant()); diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java b/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java deleted file mode 100644 index 22713bf..0000000 --- a/src/main/java/net/turniptales/discord/events/GuildMemberJoinListener.java +++ /dev/null @@ -1,51 +0,0 @@ -package net.turniptales.discord.events; - -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import java.util.Date; - -import static java.awt.Color.CYAN; -import static java.util.Objects.nonNull; -import static net.turniptales.discord.Config.BOT; -import static net.turniptales.discord.Config.COMMUNITY_TEXT_CHANNEL; -import static net.turniptales.discord.Config.PLAYER_ROLE; -import static net.turniptales.discord.Config.ROLE_0; - -public class GuildMemberJoinListener extends ListenerAdapter { - - @Override - public void onGuildMemberJoin(GuildMemberJoinEvent e) { - Guild guild = e.getGuild(); - TextChannel communityTextChannel = COMMUNITY_TEXT_CHANNEL; - TextChannel missionControlTextChannel = guild.getSystemChannel(); - if (nonNull(communityTextChannel) && nonNull(missionControlTextChannel) && nonNull(BOT) && nonNull(PLAYER_ROLE) && nonNull(ROLE_0)) { - Member member = e.getMember(); - - EmbedBuilder embedBuildercommunityTextChannel = new EmbedBuilder() - .setColor(CYAN) - .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) - .setTitle("Willkommen auf TurnipTales!") - .setDescription(member.getAsMention() + " hat den Server betreten.") - .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), member.getEffectiveAvatarUrl()) - .setTimestamp(new Date().toInstant()); - - EmbedBuilder embedBuildermissionControlTextChannel = new EmbedBuilder() - .setColor(CYAN) - .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) - .setDescription(member.getAsMention() + " hat den Server betreten.") - .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), member.getEffectiveAvatarUrl()) - .setTimestamp(new Date().toInstant()); - - communityTextChannel.sendMessageEmbeds(embedBuildercommunityTextChannel.build()).queue(); - missionControlTextChannel.sendMessageEmbeds(embedBuildermissionControlTextChannel.build()).queue(); - - guild.addRoleToMember(e.getUser(), PLAYER_ROLE).queue(); - guild.addRoleToMember(e.getUser(), ROLE_0).queue(); - } - } -} diff --git a/src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java b/src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java deleted file mode 100644 index 4f639b7..0000000 --- a/src/main/java/net/turniptales/discord/events/GuildMemberUpdateBoostTimeListener.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.turniptales.discord.events; - -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateBoostTimeEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import java.awt.Color; -import java.util.Date; - -import static java.util.Objects.nonNull; -import static net.turniptales.discord.Config.BOT; -import static net.turniptales.discord.Config.COMMUNITY_TEXT_CHANNEL; - -public class GuildMemberUpdateBoostTimeListener extends ListenerAdapter { - - @Override - public void onGuildMemberUpdateBoostTime(GuildMemberUpdateBoostTimeEvent e) { - Guild guild = e.getGuild(); - TextChannel communityTextChannel = COMMUNITY_TEXT_CHANNEL; - if (nonNull(communityTextChannel) && nonNull(BOT)) { - Member member = e.getMember(); - - EmbedBuilder embedBuilder = new EmbedBuilder() - .setColor(new Color(85, 255, 255)) - .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) - .setTitle("Danke für den Boost!") - .setDescription(member.getAsMention() + " hat den Server geboostet.") - .setFooter("Aktuelle Boosts: **" + guild.getBoostCount() + "** (" + guild.getBoostTier() + ")", member.getEffectiveAvatarUrl()) - .setTimestamp(new Date().toInstant()); - - communityTextChannel.sendMessageEmbeds(embedBuilder.build()).queue(); - } - } -} diff --git a/src/main/java/net/turniptales/discord/events/MessageReactionListener.java b/src/main/java/net/turniptales/discord/events/MessageReactionListener.java index c8e555c..239a185 100644 --- a/src/main/java/net/turniptales/discord/events/MessageReactionListener.java +++ b/src/main/java/net/turniptales/discord/events/MessageReactionListener.java @@ -7,7 +7,7 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter; import static java.util.Objects.nonNull; -import static net.turniptales.discord.Config.SURVEY_TEXT_CHANNEL; +import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; public class MessageReactionListener extends ListenerAdapter { @@ -15,7 +15,7 @@ public class MessageReactionListener extends ListenerAdapter { public void onMessageReactionAdd(MessageReactionAddEvent e) { MessageChannelUnion channel = e.getChannel(); User user = e.getUser(); - if (channel.equals(SURVEY_TEXT_CHANNEL) && nonNull(user) && !user.isBot()) { + if (channel.equals(discordBotProperties.getSurveyTextChannel()) && nonNull(user) && !user.isBot()) { channel.retrieveMessageById(e.getMessageIdLong()).queue(message -> message.getReactions().forEach(messageReaction -> messageReaction.retrieveUsers().queue(users -> { EmojiUnion emoji = messageReaction.getEmoji(); if (users.contains(user) && !emoji.equals(e.getEmoji())) { diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a0b96f3..4d990d6 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -5,3 +5,27 @@ server.error.whitelabel.enabled=false spring.main.banner-mode=off spring.output.ansi.enabled=ALWAYS + +discord.bot.token=MTE5MDcxNDY0MzU1MTg5MTQ3OA.GdvTJE.EMI9oOxjzEe-unfAXWPtOKgb2qGtWkqonPq5OY +discord.guild.id=1008928645185810463 + +discord.guild.channels.community-text-channel=1008929885764472952 +discord.guild.channels.survey-text-channel=1206336710128959519 +discord.guild.channels.ticket-text-channel=1009477703990267954 + +discord.guild.categories.ticket-category=1009478372847517727 + +discord.guild.roles.player-role=1190675464549847110 +discord.guild.roles.senior-moderator-role=1208149723547050004 +discord.guild.roles.moderator-role=1025864289346658355 +discord.guild.roles.supporter-role=1009477020427747408 + +discord.guild.roles.role-0=1134487019058372649 +discord.guild.roles.role-1-week=1134487221349650462 +discord.guild.roles.role-2-week=1134487277205192744 +discord.guild.roles.role-1-month=1134487413125820477 +discord.guild.roles.role-3-month=1134487461452583043 +discord.guild.roles.role-6-month=1134487539588268094 +discord.guild.roles.role-1-year=1134487593585745920 +discord.guild.roles.role-2-year=1134487644110336010 +discord.guild.roles.role-3-year=1134487702864142356 From 2e4049b4bd68fdd627a1ddcfdfe1d5dab8f68412 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 00:43:28 +0200 Subject: [PATCH 46/58] Update command handling --- .../discord/TurnipTalesDiscord.java | 65 ++++++++----------- .../discord/commands/CommandBase.java | 22 +++++++ .../discord/commands/StatsCommand.java | 41 ++++++------ .../discord/commands/SurveyCommand.java | 5 +- .../discord/commands/TicketCommand.java | 24 +++---- .../discord/commands/VerifyCommand.java | 23 ++++--- 6 files changed, 93 insertions(+), 87 deletions(-) create mode 100644 src/main/java/net/turniptales/discord/commands/CommandBase.java diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index 54c2e1a..da26951 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -3,17 +3,18 @@ import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; +import net.dv8tion.jda.api.interactions.commands.build.Commands; import net.turniptales.discord.commands.GiveawayCommand; import net.turniptales.discord.commands.StatsCommand; import net.turniptales.discord.commands.SurveyCommand; +import net.turniptales.discord.commands.TestCommand; import net.turniptales.discord.commands.TicketCommand; import net.turniptales.discord.commands.VerifyCommand; import net.turniptales.discord.common.api.Api; import net.turniptales.discord.common.configuration.DiscordBotProperties; import net.turniptales.discord.events.ButtonInteractionListener; -import net.turniptales.discord.events.GuildMemberJoinListener; -import net.turniptales.discord.events.GuildMemberRemoveListener; -import net.turniptales.discord.events.GuildMemberUpdateBoostTimeListener; +import net.turniptales.discord.events.GuildAccessListener; import net.turniptales.discord.events.MessageReactionListener; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -24,6 +25,7 @@ import static java.lang.System.currentTimeMillis; import static java.time.ZoneId.of; +import static net.dv8tion.jda.api.Permission.ADMINISTRATOR; import static net.dv8tion.jda.api.interactions.commands.OptionType.STRING; import static net.dv8tion.jda.api.interactions.commands.OptionType.USER; import static net.dv8tion.jda.api.requests.GatewayIntent.GUILD_MEMBERS; @@ -41,7 +43,7 @@ public class TurnipTalesDiscord implements WebMvcConfigurer { public static DiscordBotProperties discordBotProperties; public static Api api; - public static void main(String[] args) { + public static void main(String[] args) throws InterruptedException { ConfigurableApplicationContext context = SpringApplication.run(TurnipTalesDiscord.class, args); discordBotProperties = context.getBean(DiscordBotProperties.class); @@ -54,7 +56,7 @@ public static void main(String[] args) { api = new Api(); } - private static void startDiscordBot() { + private static void startDiscordBot() throws InterruptedException { discordBot = JDABuilder .createDefault(discordBotProperties.getToken()) .disableCache(MEMBER_OVERRIDES, VOICE_STATE) // Disable parts of the cache @@ -71,41 +73,30 @@ private static void startDiscordBot() { ) .addEventListeners( new ButtonInteractionListener(), - new GuildMemberJoinListener(), - new GuildMemberRemoveListener(), - new GuildMemberUpdateBoostTimeListener(), + new GuildAccessListener(), new MessageReactionListener() ) - .build(); + .build().awaitReady(); - discordBot - .upsertCommand("stats", "Deine Statistiken (nicht öffentlich) oder die eines Discord Nutzers (öffentlich)") - .addOption(USER, "player", "Discord Nutzer dessen Statistiken angezeigt werden sollen (Discord Nutzer muss sich verknüpft haben)", false) - .queue(); + discordBotProperties.getGuild().updateCommands().addCommands( + Commands.slash("stats", "Deine Statistiken (nicht öffentlich) oder die eines Discord Nutzers (öffentlich)") + .addOption(USER, "player", "Discord Nutzer dessen Statistiken angezeigt werden sollen (Discord Nutzer muss sich verknüpft haben)", false), + Commands.slash("umfrage", "Erstellt eine Umfrage") + .addOption(STRING, "question", "Frage", true) + .addOption(STRING, "description", "Beschreibung", true) + .addOption(STRING, "answer1", "Antwort 1", true) + .addOption(STRING, "answer2", "Antwort 2", true) + .addOption(STRING, "answer3", "Antwort 3", false) + .addOption(STRING, "answer4", "Antwort 4", false) + .addOption(STRING, "answer5", "Antwort 5", false), + Commands.slash("verify", "Verifiziert deinen Minecraft Account") + .addOption(STRING, "code", "Verifizierungscode", true), - discordBot - .upsertCommand("umfrage", "Erstellt eine Umfrage") - .addOption(STRING, "question", "Frage", true) - .addOption(STRING, "description", "Beschreibung", true) - .addOption(STRING, "answer1", "Antwort 1", true) - .addOption(STRING, "answer2", "Antwort 2", true) - .addOption(STRING, "answer3", "Antwort 3", false) - .addOption(STRING, "answer4", "Antwort 4", false) - .addOption(STRING, "answer5", "Antwort 5", false) - .queue(); - - discordBot - .upsertCommand("ticket", "Erstellt die Nachricht um Tickets zu erstellen") - .queue(); - - discordBot - .upsertCommand("verify", "Verifiziert deinen Minecraft Account") - .addOption(STRING, "code", "Verifizierungscode", true) - .queue(); - - discordBot - .upsertCommand("giveaway", "Lost einen Spieler anhand der Reaktionen einer Nachricht aus") - .addOption(STRING, "message", "Nachricht mit den Reaktionen", true) - .queue(); + Commands.slash("ticket", "Erstellt die Nachricht um Tickets zu erstellen") + .setDefaultPermissions(DefaultMemberPermissions.enabledFor(ADMINISTRATOR)), + Commands.slash("giveaway", "Lost einen Spieler anhand der Reaktionen einer Nachricht aus") + .addOption(STRING, "message", "Nachricht mit den Reaktionen", true) + .setDefaultPermissions(DefaultMemberPermissions.enabledFor(ADMINISTRATOR)) + ).queue(); } } diff --git a/src/main/java/net/turniptales/discord/commands/CommandBase.java b/src/main/java/net/turniptales/discord/commands/CommandBase.java new file mode 100644 index 0000000..9165dbb --- /dev/null +++ b/src/main/java/net/turniptales/discord/commands/CommandBase.java @@ -0,0 +1,22 @@ +package net.turniptales.discord.commands; + +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +public abstract class CommandBase extends ListenerAdapter { + + private final String name; + + public CommandBase(String name) { + this.name = name; + } + + public abstract void onCommand(SlashCommandInteractionEvent event); + + @Override + public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { + if (event.getName().equals(this.name)) { + onCommand(event); + } + } +} diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index 2c21ae6..6084209 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -6,7 +6,6 @@ import net.dv8tion.jda.api.entities.channel.Channel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.turniptales.discord.common.api.model.ConnectionDataValue; import net.turniptales.discord.common.api.model.PunishmentData; @@ -22,40 +21,41 @@ import static java.util.Locale.US; import static java.util.Objects.nonNull; import static java.util.concurrent.TimeUnit.SECONDS; -import static net.turniptales.discord.Config.BOT; import static net.turniptales.discord.TurnipTalesDiscord.api; +import static net.turniptales.discord.TurnipTalesDiscord.discordBot; -public class StatsCommand extends ListenerAdapter { +public class StatsCommand extends CommandBase { public static final DecimalFormatSymbols US_SYMBOLS = DecimalFormatSymbols.getInstance(US); public static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("###.##", US_SYMBOLS); - @Override - public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { - if (!e.getName().equals("stats")) { - return; - } + public StatsCommand() { + super("stats"); + } - OptionMapping playerOptionMapping = e.getOption("player"); + @Override + public void onCommand(SlashCommandInteractionEvent event) { + OptionMapping playerOptionMapping = event.getOption("player"); - Member member = e.getMember(); + Member member = event.getMember(); + String userId = event.getUser().getId(); if (nonNull(playerOptionMapping)) { try { - ConnectionDataValue connectionDataValue = api.getData(e.getUser().getId()); - MessageEmbed publicPlayerStats = isTicketChannel(e.getChannel()) ? getPrivatePlayerStats(connectionDataValue, member) : getPublicPlayerStats(connectionDataValue, member); - e.replyEmbeds(publicPlayerStats).queue(); + ConnectionDataValue connectionDataValue = api.getData(userId); + MessageEmbed publicPlayerStats = isTicketChannel(event.getChannel()) ? getPrivatePlayerStats(connectionDataValue, member) : getPublicPlayerStats(connectionDataValue, member); + event.replyEmbeds(publicPlayerStats).queue(); } catch (Exception ex) { - e.reply("Der angegebene Spieler hat seinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); - e.getHook().deleteOriginal().queueAfter(5, SECONDS); + event.reply("Der angegebene Spieler hat seinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); + event.getHook().deleteOriginal().queueAfter(5, SECONDS); } } else { try { - ConnectionDataValue connectionDataValue = api.getData(e.getUser().getId()); + ConnectionDataValue connectionDataValue = api.getData(userId); MessageEmbed privatePlayerStats = getPrivatePlayerStats(connectionDataValue, member); - e.replyEmbeds(privatePlayerStats).setEphemeral(true).queue(); + event.replyEmbeds(privatePlayerStats).setEphemeral(true).queue(); } catch (Exception ex) { - e.reply("Du hast deinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); - e.getHook().deleteOriginal().queueAfter(5, SECONDS); + event.reply("Du hast deinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); + event.getHook().deleteOriginal().queueAfter(5, SECONDS); } } } @@ -95,11 +95,10 @@ private MessageEmbed getPrivatePlayerStats(ConnectionDataValue connectionDataVal } private EmbedBuilder getDefaultEmbedBuilder(ConnectionDataValue connectionDataValue, Member member) { - assert BOT != null; return new EmbedBuilder() .setColor(CYAN) .setThumbnail("https://minotar.net/helm/" + connectionDataValue.getMinecraftUuid() + "/300.png") - .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) .setTitle("Statistiken von " + connectionDataValue.getMinecraftName()) .setDescription("**Role**: " + connectionDataValue.getRole()) .setFooter(member.getEffectiveName(), member.getEffectiveAvatarUrl()) diff --git a/src/main/java/net/turniptales/discord/commands/SurveyCommand.java b/src/main/java/net/turniptales/discord/commands/SurveyCommand.java index c6e5fb4..f23ebfb 100644 --- a/src/main/java/net/turniptales/discord/commands/SurveyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/SurveyCommand.java @@ -22,7 +22,7 @@ import static net.dv8tion.jda.api.Permission.ADMINISTRATOR; import static net.dv8tion.jda.api.entities.emoji.Emoji.fromUnicode; import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; -import static net.turniptales.discord.Config.BOT; +import static net.turniptales.discord.TurnipTalesDiscord.discordBot; public class SurveyCommand extends ListenerAdapter { @@ -51,7 +51,6 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { Survey survey = new Survey(questionOptionMapping.getAsString(), descriptionOptionMapping.getAsString(), answers); Member member = e.getMember(); - assert BOT != null; pendingSurveys.put(member, survey); @@ -77,7 +76,7 @@ public MessageEmbed toEmbed(Member member) { EmbedBuilder embedBuilder = new EmbedBuilder() .setColor(CYAN) .setTitle(this.title) - .setAuthor("TurnipTales", "https://turniptales.net/", BOT.getEffectiveAvatarUrl()) + .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) .setDescription(this.description) .setFooter("Umfrage erstellt von " + member.getEffectiveName(), member.getEffectiveAvatarUrl()) .setTimestamp(new Date().toInstant()); diff --git a/src/main/java/net/turniptales/discord/commands/TicketCommand.java b/src/main/java/net/turniptales/discord/commands/TicketCommand.java index 0ecbaac..61f97a1 100644 --- a/src/main/java/net/turniptales/discord/commands/TicketCommand.java +++ b/src/main/java/net/turniptales/discord/commands/TicketCommand.java @@ -2,35 +2,31 @@ import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.turniptales.discord.Config; import java.awt.Color; -import java.util.Objects; -import static net.dv8tion.jda.api.Permission.ADMINISTRATOR; import static net.dv8tion.jda.api.entities.emoji.Emoji.fromUnicode; import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; +import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; -public class TicketCommand extends ListenerAdapter { +public class TicketCommand extends CommandBase { - @Override - public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { - if (!e.getName().equals("ticket") || !Objects.requireNonNull(e.getMember()).hasPermission(ADMINISTRATOR)) { - return; - } + public TicketCommand() { + super("ticket"); + } - e.deferReply(true).queue(); + @Override + public void onCommand(SlashCommandInteractionEvent event) { + event.deferReply(true).queue(); EmbedBuilder embedBuilder = new EmbedBuilder() .setColor(new Color(0x609fee)) .setTitle("Ticket") .addField("🎫 **Hier kannst du ein Ticket erstellen um schnell Hilfe zu erhalten oder sonstige Fragen zu klären.**", "Bei der Erstellung eines Tickets wirst du nach deinem Minecraft Namen und Anliegen gefragt.", false); - assert Config.TICKET_TEXT_CHANNEL != null; - Config.TICKET_TEXT_CHANNEL + discordBotProperties.getTicketTextChannel() .sendMessageEmbeds(embedBuilder.build()) .addActionRow(success("createTicketAddButton", "Neues Ticket").withEmoji(fromUnicode("U+1F3AB"))) .queue(); - e.getHook().deleteOriginal().queue(); + event.getHook().deleteOriginal().queue(); } } diff --git a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java index 3cac80b..1baceec 100644 --- a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java +++ b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java @@ -1,7 +1,6 @@ package net.turniptales.discord.commands; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.turniptales.discord.common.api.model.ConnectionDataValue; import org.springframework.http.ResponseEntity; @@ -10,21 +9,21 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static net.turniptales.discord.TurnipTalesDiscord.api; -public class VerifyCommand extends ListenerAdapter { +public class VerifyCommand extends CommandBase { - @Override - public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { - if (!e.getName().equals("verify")) { - return; - } + public VerifyCommand() { + super("verify"); + } - OptionMapping codeOptionMapping = e.getOption("code"); + @Override + public void onCommand(SlashCommandInteractionEvent event) { + OptionMapping codeOptionMapping = event.getOption("code"); if (isNull(codeOptionMapping)) { - e.reply("Gib einen Verifizierungscode an!").setEphemeral(true).queue(); + event.reply("Gib einen Verifizierungscode an!").setEphemeral(true).queue(); return; } - String accountUserId = e.getUser().getId(); + String accountUserId = event.getUser().getId(); ResponseEntity response = api.connect(accountUserId, codeOptionMapping.getAsString()); boolean success = response.getStatusCode().is2xxSuccessful(); @@ -36,7 +35,7 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { message = "Dein Discord Account konnte nicht mit deinem Minecraft Account verknüpft werden."; } - e.reply(message).setEphemeral(true).queue(); - e.getHook().deleteOriginal().queueAfter(5, SECONDS); + event.reply(message).setEphemeral(true).queue(); + event.getHook().deleteOriginal().queueAfter(5, SECONDS); } } From 8df246561e297ddf1fad803e5b22b4a95118ce0a Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 14:28:55 +0200 Subject: [PATCH 47/58] Add RolesCommand for information about roles --- .../discord/TurnipTalesDiscord.java | 3 ++ .../discord/commands/RolesCommand.java | 43 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/main/java/net/turniptales/discord/commands/RolesCommand.java diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index da26951..e37ee53 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -6,6 +6,7 @@ import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; import net.dv8tion.jda.api.interactions.commands.build.Commands; import net.turniptales.discord.commands.GiveawayCommand; +import net.turniptales.discord.commands.RolesCommand; import net.turniptales.discord.commands.StatsCommand; import net.turniptales.discord.commands.SurveyCommand; import net.turniptales.discord.commands.TestCommand; @@ -66,6 +67,7 @@ private static void startDiscordBot() throws InterruptedException { .enableIntents(GUILD_MEMBERS) .addEventListeners( new GiveawayCommand(), + new RolesCommand(), new StatsCommand(), new SurveyCommand(), new TicketCommand(), @@ -79,6 +81,7 @@ private static void startDiscordBot() throws InterruptedException { .build().awaitReady(); discordBotProperties.getGuild().updateCommands().addCommands( + Commands.slash("rollen", "Informationen zu den Rollen auf diesem Discord"), Commands.slash("stats", "Deine Statistiken (nicht öffentlich) oder die eines Discord Nutzers (öffentlich)") .addOption(USER, "player", "Discord Nutzer dessen Statistiken angezeigt werden sollen (Discord Nutzer muss sich verknüpft haben)", false), Commands.slash("umfrage", "Erstellt eine Umfrage") diff --git a/src/main/java/net/turniptales/discord/commands/RolesCommand.java b/src/main/java/net/turniptales/discord/commands/RolesCommand.java new file mode 100644 index 0000000..b74f57a --- /dev/null +++ b/src/main/java/net/turniptales/discord/commands/RolesCommand.java @@ -0,0 +1,43 @@ +package net.turniptales.discord.commands; + +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; + +import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; + +public class RolesCommand extends CommandBase { + + public RolesCommand() { + super("rollen"); + } + + @Override + public void onCommand(SlashCommandInteractionEvent event) { + event.reply(""" + Die Standard Rolle für jedes Mitglied ist `%s`. + + Wenn man längere Zeit auf diesem Discord ist, wird einem automatisch eine Rolle zugewiesen. Je nachdem, wie lang man schon auf diesem Discord ist, erhält man eine höhere Rolle: + + `%s` ➜ direkt nach Serverbeitritt + `%s` ➜ nach einer Woche + `%s` ➜ nach zwei Wochen + `%s` ➜ nach einem Monat + `%s` ➜ nach drei Monaten + `%s` ➜ nach sechs Monaten + `%s` ➜ nach einem Jahr + `%s` ➜ nach zwei Jahren + `%s` ➜ nach drei Jahren + + So sieht man auch gut, wer schon lang dabei ist und sich schon gut auskennen könnte. Die Rollen werden durch den TurnipTales Bot automatisch vergeben und können dadurch nicht erstattet werden, wenn man den Server zwischenzeitlich verlässt. + """.formatted( + discordBotProperties.getPlayerRole().getName(), + discordBotProperties.getRole0().getName(), + discordBotProperties.getRole1Week().getName(), + discordBotProperties.getRole2Week().getName(), + discordBotProperties.getRole1Month().getName(), + discordBotProperties.getRole3Month().getName(), + discordBotProperties.getRole6Month().getName(), + discordBotProperties.getRole1Year().getName(), + discordBotProperties.getRole2Year().getName(), + discordBotProperties.getRole3Year().getName())).queue(); + } +} From 1902d409d09ac7347d304ca99f179754e00d6c15 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 14:32:41 +0200 Subject: [PATCH 48/58] Remove survey logic because new discord feature for build-in surveys --- .../discord/TurnipTalesDiscord.java | 14 +-- .../discord/commands/SurveyCommand.java | 103 ------------------ .../configuration/DiscordBotProperties.java | 7 -- .../events/MessageReactionListener.java | 27 ----- src/main/resources/application.properties | 1 - 5 files changed, 1 insertion(+), 151 deletions(-) delete mode 100644 src/main/java/net/turniptales/discord/commands/SurveyCommand.java delete mode 100644 src/main/java/net/turniptales/discord/events/MessageReactionListener.java diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index e37ee53..4ab62c8 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -8,7 +8,6 @@ import net.turniptales.discord.commands.GiveawayCommand; import net.turniptales.discord.commands.RolesCommand; import net.turniptales.discord.commands.StatsCommand; -import net.turniptales.discord.commands.SurveyCommand; import net.turniptales.discord.commands.TestCommand; import net.turniptales.discord.commands.TicketCommand; import net.turniptales.discord.commands.VerifyCommand; @@ -16,7 +15,6 @@ import net.turniptales.discord.common.configuration.DiscordBotProperties; import net.turniptales.discord.events.ButtonInteractionListener; import net.turniptales.discord.events.GuildAccessListener; -import net.turniptales.discord.events.MessageReactionListener; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @@ -69,14 +67,12 @@ private static void startDiscordBot() throws InterruptedException { new GiveawayCommand(), new RolesCommand(), new StatsCommand(), - new SurveyCommand(), new TicketCommand(), new VerifyCommand() ) .addEventListeners( new ButtonInteractionListener(), - new GuildAccessListener(), - new MessageReactionListener() + new GuildAccessListener() ) .build().awaitReady(); @@ -84,14 +80,6 @@ private static void startDiscordBot() throws InterruptedException { Commands.slash("rollen", "Informationen zu den Rollen auf diesem Discord"), Commands.slash("stats", "Deine Statistiken (nicht öffentlich) oder die eines Discord Nutzers (öffentlich)") .addOption(USER, "player", "Discord Nutzer dessen Statistiken angezeigt werden sollen (Discord Nutzer muss sich verknüpft haben)", false), - Commands.slash("umfrage", "Erstellt eine Umfrage") - .addOption(STRING, "question", "Frage", true) - .addOption(STRING, "description", "Beschreibung", true) - .addOption(STRING, "answer1", "Antwort 1", true) - .addOption(STRING, "answer2", "Antwort 2", true) - .addOption(STRING, "answer3", "Antwort 3", false) - .addOption(STRING, "answer4", "Antwort 4", false) - .addOption(STRING, "answer5", "Antwort 5", false), Commands.slash("verify", "Verifiziert deinen Minecraft Account") .addOption(STRING, "code", "Verifizierungscode", true), diff --git a/src/main/java/net/turniptales/discord/commands/SurveyCommand.java b/src/main/java/net/turniptales/discord/commands/SurveyCommand.java deleted file mode 100644 index f23ebfb..0000000 --- a/src/main/java/net/turniptales/discord/commands/SurveyCommand.java +++ /dev/null @@ -1,103 +0,0 @@ -package net.turniptales.discord.commands; - -import lombok.Data; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.entities.emoji.Emoji; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.interactions.commands.OptionMapping; - -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Stream; - -import static java.awt.Color.CYAN; -import static java.util.Objects.nonNull; -import static java.util.concurrent.TimeUnit.SECONDS; -import static net.dv8tion.jda.api.Permission.ADMINISTRATOR; -import static net.dv8tion.jda.api.entities.emoji.Emoji.fromUnicode; -import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; -import static net.turniptales.discord.TurnipTalesDiscord.discordBot; - -public class SurveyCommand extends ListenerAdapter { - - public static final Map pendingSurveys = new HashMap<>(); - - @Override - public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { - if (!e.getName().equals("umfrage") || !Objects.requireNonNull(e.getMember()).hasPermission(ADMINISTRATOR)) { - return; - } - - OptionMapping questionOptionMapping = e.getOption("question"); - OptionMapping descriptionOptionMapping = e.getOption("description"); - OptionMapping answer1OptionMapping = e.getOption("answer1"); - OptionMapping answer2OptionMapping = e.getOption("answer2"); - OptionMapping answer3OptionMapping = e.getOption("answer3"); - OptionMapping answer4OptionMapping = e.getOption("answer4"); - OptionMapping answer5OptionMapping = e.getOption("answer5"); - - List answers = Stream.of(answer1OptionMapping, answer2OptionMapping, answer3OptionMapping, answer4OptionMapping, answer5OptionMapping) - .filter(Objects::nonNull) - .map(OptionMapping::getAsString) - .toList(); - - if (nonNull(questionOptionMapping) && nonNull(descriptionOptionMapping) && answers.size() > 1) { - Survey survey = new Survey(questionOptionMapping.getAsString(), descriptionOptionMapping.getAsString(), answers); - - Member member = e.getMember(); - - pendingSurveys.put(member, survey); - - e.replyEmbeds(survey.toEmbed(member)) - .setEphemeral(true) - .addActionRow(success("sendSurvey", "Starten")) - .queue(); - e.getHook().deleteOriginal().queueAfter(30, SECONDS); - } else { - e.reply("Es müssen mindestens eine Frage und zwei Antworten angegeben werden.").setEphemeral(true).queue(); - e.getHook().deleteOriginal().queueAfter(5, SECONDS); - } - } - - @Data - public static class Survey { - - private final String title; - private final String description; - private final List answers; - - public MessageEmbed toEmbed(Member member) { - EmbedBuilder embedBuilder = new EmbedBuilder() - .setColor(CYAN) - .setTitle(this.title) - .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) - .setDescription(this.description) - .setFooter("Umfrage erstellt von " + member.getEffectiveName(), member.getEffectiveAvatarUrl()) - .setTimestamp(new Date().toInstant()); - - for (int i = 0; i < answers.size(); i++) { - embedBuilder.addField("Antwort " + (i + 1), this.answers.get(i), false); - } - - return embedBuilder.build(); - } - - public List getReactions() { - List emojis = List.of( - fromUnicode("U+0031 U+20E3"), - fromUnicode("U+0032 U+20E3"), - fromUnicode("U+0033 U+20E3"), - fromUnicode("U+0034 U+20E3"), - fromUnicode("U+0035 U+20E3") - ); - - return emojis.subList(0, this.answers.size()); - } - } -} diff --git a/src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java b/src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java index 56b0a85..a55080d 100644 --- a/src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java +++ b/src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java @@ -23,9 +23,6 @@ public class DiscordBotProperties { @Value("${discord.guild.channels.community-text-channel}") private String communityTextChannel; - @Value("${discord.guild.channels.survey-text-channel}") - private String surveyTextChannel; - @Value("${discord.guild.channels.ticket-text-channel}") private String ticketTextChannel; @@ -79,10 +76,6 @@ public TextChannel getCommunityTextChannel() { return getGuild().getTextChannelById(this.communityTextChannel); } - public TextChannel getSurveyTextChannel() { - return getGuild().getTextChannelById(this.surveyTextChannel); - } - public TextChannel getTicketTextChannel() { return getGuild().getTextChannelById(this.ticketTextChannel); } diff --git a/src/main/java/net/turniptales/discord/events/MessageReactionListener.java b/src/main/java/net/turniptales/discord/events/MessageReactionListener.java deleted file mode 100644 index 239a185..0000000 --- a/src/main/java/net/turniptales/discord/events/MessageReactionListener.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.turniptales.discord.events; - -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion; -import net.dv8tion.jda.api.entities.emoji.EmojiUnion; -import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import static java.util.Objects.nonNull; -import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; - -public class MessageReactionListener extends ListenerAdapter { - - @Override - public void onMessageReactionAdd(MessageReactionAddEvent e) { - MessageChannelUnion channel = e.getChannel(); - User user = e.getUser(); - if (channel.equals(discordBotProperties.getSurveyTextChannel()) && nonNull(user) && !user.isBot()) { - channel.retrieveMessageById(e.getMessageIdLong()).queue(message -> message.getReactions().forEach(messageReaction -> messageReaction.retrieveUsers().queue(users -> { - EmojiUnion emoji = messageReaction.getEmoji(); - if (users.contains(user) && !emoji.equals(e.getEmoji())) { - message.removeReaction(emoji, user).queue(); - } - }))); - } - } -} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4d990d6..b0eb5a4 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -10,7 +10,6 @@ discord.bot.token=MTE5MDcxNDY0MzU1MTg5MTQ3OA.GdvTJE.EMI9oOxjzEe-unfAXWPtOKgb2qGt discord.guild.id=1008928645185810463 discord.guild.channels.community-text-channel=1008929885764472952 -discord.guild.channels.survey-text-channel=1206336710128959519 discord.guild.channels.ticket-text-channel=1009477703990267954 discord.guild.categories.ticket-category=1009478372847517727 From 65e89e44ce4258e478439e7ade478a0ad8394572 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 16:08:33 +0200 Subject: [PATCH 49/58] Update StatsCommand handling and response in api --- .../discord/commands/StatsCommand.java | 38 ++++++++++--------- .../turniptales/discord/common/api/Api.java | 9 ++++- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index 6084209..cced232 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -9,6 +9,7 @@ import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.turniptales.discord.common.api.model.ConnectionDataValue; import net.turniptales.discord.common.api.model.PunishmentData; +import org.springframework.http.ResponseEntity; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; @@ -18,6 +19,7 @@ import static java.awt.Color.CYAN; import static java.lang.String.valueOf; +import static java.lang.System.currentTimeMillis; import static java.util.Locale.US; import static java.util.Objects.nonNull; import static java.util.concurrent.TimeUnit.SECONDS; @@ -39,24 +41,26 @@ public void onCommand(SlashCommandInteractionEvent event) { Member member = event.getMember(); String userId = event.getUser().getId(); - if (nonNull(playerOptionMapping)) { - try { - ConnectionDataValue connectionDataValue = api.getData(userId); - MessageEmbed publicPlayerStats = isTicketChannel(event.getChannel()) ? getPrivatePlayerStats(connectionDataValue, member) : getPublicPlayerStats(connectionDataValue, member); - event.replyEmbeds(publicPlayerStats).queue(); - } catch (Exception ex) { - event.reply("Der angegebene Spieler hat seinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); - event.getHook().deleteOriginal().queueAfter(5, SECONDS); - } + + boolean notSelf = nonNull(playerOptionMapping); + String targetUserId = notSelf ? playerOptionMapping.getAsString() : userId; + ResponseEntity responseEntity = api.getData(targetUserId); + + boolean isConnected = responseEntity.getStatusCode().is2xxSuccessful(); + if (!isConnected) { + event.reply((notSelf ? "Der Spieler hat seinen" : "Du hast deinen") + " Discord Account noch nicht mit dem Minecraft Account verknüpft.\n-# 🚮 ").setEphemeral(true).queue(); + event.getHook().deleteOriginal().queueAfter(10, SECONDS); + return; + } + + ConnectionDataValue targetConnectionDataValue = responseEntity.getBody(); + + if (notSelf) { + MessageEmbed publicPlayerStats = isTicketChannel(event.getChannel()) ? getPrivatePlayerStats(targetConnectionDataValue, member) : getPublicPlayerStats(targetConnectionDataValue, member); + event.replyEmbeds(publicPlayerStats).queue(); } else { - try { - ConnectionDataValue connectionDataValue = api.getData(userId); - MessageEmbed privatePlayerStats = getPrivatePlayerStats(connectionDataValue, member); - event.replyEmbeds(privatePlayerStats).setEphemeral(true).queue(); - } catch (Exception ex) { - event.reply("Du hast deinen Minecraft Account noch nicht verknüpft.").setEphemeral(true).queue(); - event.getHook().deleteOriginal().queueAfter(5, SECONDS); - } + MessageEmbed privatePlayerStats = getPrivatePlayerStats(targetConnectionDataValue, member); + event.replyEmbeds(privatePlayerStats).setEphemeral(true).queue(); } } diff --git a/src/main/java/net/turniptales/discord/common/api/Api.java b/src/main/java/net/turniptales/discord/common/api/Api.java index 19271cf..d734517 100644 --- a/src/main/java/net/turniptales/discord/common/api/Api.java +++ b/src/main/java/net/turniptales/discord/common/api/Api.java @@ -30,9 +30,14 @@ public class Api { /** * {@link ConnectionDataValue} */ - public ConnectionDataValue getData(String accountUserId) { + public ResponseEntity getData(String accountUserId) { String url = format("/data?discordUserId=%s", accountUserId); - return getGson().fromJson(sendRequest(url, GET).getBody(), ConnectionDataValue.class); + + ResponseEntity responseEntity = sendRequest(url, GET); + + return responseEntity.getStatusCode().is2xxSuccessful() + ? ResponseEntity.ok(getGson().fromJson(responseEntity.getBody(), ConnectionDataValue.class)) + : ResponseEntity.status(responseEntity.getStatusCode()).body(null); } public ResponseEntity connect(String accountUserId, String code) { From 368300d350c7d0ec890f1df46dfb5fb6cdf7ddd9 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 19:40:22 +0200 Subject: [PATCH 50/58] Update button interaction handling --- .../discord/TurnipTalesDiscord.java | 16 +- .../discord/buttons/ButtonBase.java | 23 +++ .../buttons/GiveawayWinnerPublishButton.java | 20 +++ .../discord/buttons/SyncButton.java | 93 +++++++++++ .../buttons/TicketCloseAbortButton.java | 15 ++ .../discord/buttons/TicketCloseButton.java | 27 ++++ .../buttons/TicketCloseConfirmButton.java | 23 +++ .../discord/buttons/TicketCreateButton.java | 98 ++++++++++++ .../events/ButtonInteractionListener.java | 144 ------------------ 9 files changed, 313 insertions(+), 146 deletions(-) create mode 100644 src/main/java/net/turniptales/discord/buttons/ButtonBase.java create mode 100644 src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java create mode 100644 src/main/java/net/turniptales/discord/buttons/SyncButton.java create mode 100644 src/main/java/net/turniptales/discord/buttons/TicketCloseAbortButton.java create mode 100644 src/main/java/net/turniptales/discord/buttons/TicketCloseButton.java create mode 100644 src/main/java/net/turniptales/discord/buttons/TicketCloseConfirmButton.java create mode 100644 src/main/java/net/turniptales/discord/buttons/TicketCreateButton.java delete mode 100644 src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index 4ab62c8..b7502f9 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -5,6 +5,12 @@ import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; import net.dv8tion.jda.api.interactions.commands.build.Commands; +import net.turniptales.discord.buttons.GiveawayWinnerPublishButton; +import net.turniptales.discord.buttons.SyncButton; +import net.turniptales.discord.buttons.TicketCloseAbortButton; +import net.turniptales.discord.buttons.TicketCloseButton; +import net.turniptales.discord.buttons.TicketCloseConfirmButton; +import net.turniptales.discord.buttons.TicketCreateButton; import net.turniptales.discord.commands.GiveawayCommand; import net.turniptales.discord.commands.RolesCommand; import net.turniptales.discord.commands.StatsCommand; @@ -13,7 +19,6 @@ import net.turniptales.discord.commands.VerifyCommand; import net.turniptales.discord.common.api.Api; import net.turniptales.discord.common.configuration.DiscordBotProperties; -import net.turniptales.discord.events.ButtonInteractionListener; import net.turniptales.discord.events.GuildAccessListener; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -71,9 +76,16 @@ private static void startDiscordBot() throws InterruptedException { new VerifyCommand() ) .addEventListeners( - new ButtonInteractionListener(), new GuildAccessListener() ) + .addEventListeners( + new GiveawayWinnerPublishButton(), + new SyncButton(), + new TicketCloseAbortButton(), + new TicketCloseButton(), + new TicketCloseConfirmButton(), + new TicketCreateButton() + ) .build().awaitReady(); discordBotProperties.getGuild().updateCommands().addCommands( diff --git a/src/main/java/net/turniptales/discord/buttons/ButtonBase.java b/src/main/java/net/turniptales/discord/buttons/ButtonBase.java new file mode 100644 index 0000000..cbcaa1c --- /dev/null +++ b/src/main/java/net/turniptales/discord/buttons/ButtonBase.java @@ -0,0 +1,23 @@ +package net.turniptales.discord.buttons; + +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +public abstract class ButtonBase extends ListenerAdapter { + + private final String name; + + public ButtonBase(String name) { + this.name = name; + } + + public abstract void onButtonClick(ButtonInteractionEvent event); + + @Override + public void onButtonInteraction(ButtonInteractionEvent event) { + String componentId = event.getComponentId(); + if (componentId.equalsIgnoreCase(this.name)) { + onButtonClick(event); + } + } +} diff --git a/src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java b/src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java new file mode 100644 index 0000000..cfcefb4 --- /dev/null +++ b/src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java @@ -0,0 +1,20 @@ +package net.turniptales.discord.buttons; + +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static net.turniptales.discord.commands.GiveawayCommand.giveaways; + +public class GiveawayWinnerPublishButton extends ButtonBase { + + public GiveawayWinnerPublishButton() { + super("btn_giveaway_winner_publish_button"); + } + + @Override + public void onButtonClick(ButtonInteractionEvent event) { + giveaways.get(event.getUser()).publishWinner(); + event.reply("Gewinner veröffentlicht!").setEphemeral(true).queue(); + event.getHook().deleteOriginal().queueAfter(5, SECONDS); + } +} diff --git a/src/main/java/net/turniptales/discord/buttons/SyncButton.java b/src/main/java/net/turniptales/discord/buttons/SyncButton.java new file mode 100644 index 0000000..50e65f4 --- /dev/null +++ b/src/main/java/net/turniptales/discord/buttons/SyncButton.java @@ -0,0 +1,93 @@ +package net.turniptales.discord.buttons; + +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.text.TextInput; +import net.dv8tion.jda.api.interactions.components.text.TextInputStyle; +import net.dv8tion.jda.api.interactions.modals.Modal; +import net.turniptales.discord.common.api.model.ConnectionDataValue; +import org.springframework.http.ResponseEntity; + +import java.util.HashMap; +import java.util.Map; + +import static java.lang.System.currentTimeMillis; +import static java.util.Objects.requireNonNull; +import static java.util.concurrent.TimeUnit.SECONDS; +import static net.dv8tion.jda.api.interactions.modals.Modal.create; +import static net.turniptales.discord.TurnipTalesDiscord.api; + +public class SyncButton extends ButtonBase { + + private final Map lastSync = new HashMap<>(); + + public SyncButton() { + super("btn_sync"); + } + + @Override + public void onButtonClick(ButtonInteractionEvent event) { + User user = event.getUser(); + if (currentTimeMillis() - this.lastSync.getOrDefault(user, 0L) <= SECONDS.toMillis(30)) { + event.reply("Du hast bereits vor weniger als 30 Sekunden deine Berechtigungen synchronisiert!").setEphemeral(true).queue(); + return; + } + + this.lastSync.put(user, currentTimeMillis()); + + ResponseEntity responseEntity = api.getData(user.getId()); + + boolean connected = responseEntity.getStatusCode().is2xxSuccessful(); + + if (connected) { + synchronise(responseEntity.getBody()); + event.reply("Du hast deine Rechte synchronisiert.\n-# 🚮 ").setEphemeral(true).queue(); + event.getHook().deleteOriginal().queueAfter(10, SECONDS); + } else { + event.replyModal(getVerificationModal()).queue(); + } + } + + @Override + public void onModalInteraction(ModalInteractionEvent event) { + if (!event.getModalId().equalsIgnoreCase("mdl_verification")) { + return; + } + + String discordCode = requireNonNull(event.getValue("tip_discord_code")).getAsString(); + String accountUserId = event.getUser().getId(); + + ResponseEntity response = api.connect(accountUserId, discordCode); + boolean success = response.getStatusCode().is2xxSuccessful(); + + String message; + if (success) { + ConnectionDataValue connectionDataValue = api.getData(accountUserId).getBody(); + synchronise(connectionDataValue); + message = "Du hast deinen Discord Account mit dem Minecraft Account " + connectionDataValue.getMinecraftName() + " verknüpft!"; + } else { + message = "Dein Discord Account konnte nicht mit deinem Minecraft Account verknüpft werden."; + } + + event.reply(message + "\n-# 🚮 ").setEphemeral(true).queue(); + event.getHook().deleteOriginal().queueAfter(10, SECONDS); + } + + private void synchronise(ConnectionDataValue connectionDataValue) { + System.out.println(connectionDataValue.getMinecraftName()); + } + + private Modal getVerificationModal() { + TextInput discordCodeInput = TextInput.create("tip_discord_code", "Discord Code", TextInputStyle.SHORT) + .setMinLength(8) + .setMaxLength(8) + .setRequired(true) + .build(); + + return create("mdl_verification", "Verifizierung") + .addComponents(ActionRow.of(discordCodeInput)) + .build(); + } +} diff --git a/src/main/java/net/turniptales/discord/buttons/TicketCloseAbortButton.java b/src/main/java/net/turniptales/discord/buttons/TicketCloseAbortButton.java new file mode 100644 index 0000000..d5ef62f --- /dev/null +++ b/src/main/java/net/turniptales/discord/buttons/TicketCloseAbortButton.java @@ -0,0 +1,15 @@ +package net.turniptales.discord.buttons; + +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; + +public class TicketCloseAbortButton extends ButtonBase { + + public TicketCloseAbortButton() { + super("btn_ticket_close_abort"); + } + + @Override + public void onButtonClick(ButtonInteractionEvent event) { + event.getMessage().delete().queue(); + } +} diff --git a/src/main/java/net/turniptales/discord/buttons/TicketCloseButton.java b/src/main/java/net/turniptales/discord/buttons/TicketCloseButton.java new file mode 100644 index 0000000..75c0bb4 --- /dev/null +++ b/src/main/java/net/turniptales/discord/buttons/TicketCloseButton.java @@ -0,0 +1,27 @@ +package net.turniptales.discord.buttons; + +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; + +import java.util.Objects; + +import static net.dv8tion.jda.api.interactions.components.buttons.Button.danger; +import static net.dv8tion.jda.api.interactions.components.buttons.Button.secondary; +import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; + +public class TicketCloseButton extends ButtonBase { + + public TicketCloseButton() { + super("btn_ticket_close"); + } + + @Override + public void onButtonClick(ButtonInteractionEvent event) { + TextChannel textChannel = event.getChannel().asTextChannel(); + if (Objects.equals(textChannel.getParentCategory(), discordBotProperties.getTicketCategory()) && textChannel.getName().startsWith("ticket-")) { + event.reply("Möchtest Du das Ticket wirklich schließen?") + .addActionRow(danger("btn_ticket_close_confirm", "Bestätigen"), secondary("btn_ticket_close_abort", "Abbrechen")) + .queue(); + } + } +} diff --git a/src/main/java/net/turniptales/discord/buttons/TicketCloseConfirmButton.java b/src/main/java/net/turniptales/discord/buttons/TicketCloseConfirmButton.java new file mode 100644 index 0000000..8b7a0b7 --- /dev/null +++ b/src/main/java/net/turniptales/discord/buttons/TicketCloseConfirmButton.java @@ -0,0 +1,23 @@ +package net.turniptales.discord.buttons; + +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; + +import java.util.Objects; + +import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; + +public class TicketCloseConfirmButton extends ButtonBase { + + public TicketCloseConfirmButton() { + super("btn_ticket_close_confirm"); + } + + @Override + public void onButtonClick(ButtonInteractionEvent event) { + TextChannel textChannel = event.getChannel().asTextChannel(); + if (Objects.equals(textChannel.getParentCategory(), discordBotProperties.getTicketCategory()) && textChannel.getName().startsWith("ticket-")) { + textChannel.delete().queue(); + } + } +} diff --git a/src/main/java/net/turniptales/discord/buttons/TicketCreateButton.java b/src/main/java/net/turniptales/discord/buttons/TicketCreateButton.java new file mode 100644 index 0000000..9b11210 --- /dev/null +++ b/src/main/java/net/turniptales/discord/buttons/TicketCreateButton.java @@ -0,0 +1,98 @@ +package net.turniptales.discord.buttons; + +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; +import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.text.TextInput; +import net.dv8tion.jda.api.interactions.components.text.TextInputStyle; +import net.dv8tion.jda.api.interactions.modals.Modal; + +import java.util.EnumSet; +import java.util.Objects; + +import static java.util.Objects.requireNonNull; +import static net.dv8tion.jda.api.Permission.VIEW_CHANNEL; +import static net.dv8tion.jda.api.entities.emoji.Emoji.fromUnicode; +import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; +import static net.dv8tion.jda.api.interactions.components.text.TextInputStyle.PARAGRAPH; +import static net.dv8tion.jda.api.interactions.modals.Modal.create; +import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; + +public class TicketCreateButton extends ButtonBase { + + public TicketCreateButton() { + super("btn_ticket_create"); + } + + @Override + public void onButtonClick(ButtonInteractionEvent event) { + Member member = event.getMember(); + assert member != null; + String memberId = member.getId(); + + boolean hasTicketChannel = discordBotProperties.getTicketCategory().getChannels().stream() + .map(guildChannel -> discordBotProperties.getGuild().getTextChannelById(guildChannel.getId())) + .filter(Objects::nonNull) + .map(StandardGuildMessageChannel::getTopic) + .filter(Objects::nonNull) + .anyMatch(s -> s.contains(memberId)); + + if (hasTicketChannel) { + event.reply("Du hast bereits einen Ticket Channel!").setEphemeral(true).queue(); + return; + } + + event.replyModal(getTicketModal()).queue(); + } + + @Override + public void onModalInteraction(ModalInteractionEvent event) { + if (!event.getModalId().equalsIgnoreCase("mdl_ticket")) { + return; + } + + Member member = event.getMember(); + assert member != null; + String memberId = member.getId(); + String userName = member.getUser().getName(); + + String minecraftName = requireNonNull(event.getValue("tip_minecraft_name")).getAsString(); + String log = requireNonNull(event.getValue("tip_topic")).getAsString(); + + Role supporterRole = discordBotProperties.getSupporterRole(); + Role moderatorRole = discordBotProperties.getModeratorRole(); + discordBotProperties.getTicketCategory().createTextChannel("ticket-" + userName) + .setTopic("Ticket von " + userName + " (" + memberId + ")") + .addPermissionOverride(discordBotProperties.getGuild().getPublicRole(), null, EnumSet.of(VIEW_CHANNEL)) + .addPermissionOverride(member, EnumSet.of(VIEW_CHANNEL), null) + .addPermissionOverride(discordBotProperties.getSeniorModeratorRole(), EnumSet.of(VIEW_CHANNEL), null) + .addPermissionOverride(moderatorRole, EnumSet.of(VIEW_CHANNEL), null) + .addPermissionOverride(supporterRole, EnumSet.of(VIEW_CHANNEL), null) + .queue(textChannel -> textChannel + .sendMessage("Hey " + member.getAsMention() + "! Danke dass du ein Ticket erstellt hast. Die " + supporterRole.getAsMention() + " und " + moderatorRole.getAsMention() + " werden Dir schnellstmöglich deine Frage beantworten oder Dir helfen.\n" + + "Spieler: " + minecraftName + "\n" + + "Anliegen: " + log) + .addActionRow(success("closeTicket", "Ticket schließen").withEmoji(fromUnicode("U+1F512"))) + .queue(message -> event.reply("Du hast ein Ticket erstellt: " + message.getJumpUrl()).setEphemeral(true).queue())); + } + + private Modal getTicketModal() { + TextInput minecraftNameTextInput = TextInput.create("tip_minecraft_name", "Minecraft Name", TextInputStyle.SHORT) + .setMinLength(3) + .setMaxLength(16) + .setRequired(true) + .build(); + + TextInput logInput = TextInput.create("tip_topic", "Anliegen", PARAGRAPH) + .setRequired(true) + .setPlaceholder("Hey, wie kann ich mich im Bauteam bewerben?") + .build(); + + return create("mdl_ticket", "Neues Ticket") + .addComponents(ActionRow.of(minecraftNameTextInput), ActionRow.of(logInput)) + .build(); + } +} diff --git a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java b/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java deleted file mode 100644 index 039e8e9..0000000 --- a/src/main/java/net/turniptales/discord/events/ButtonInteractionListener.java +++ /dev/null @@ -1,144 +0,0 @@ -package net.turniptales.discord.events; - -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.Role; -import net.dv8tion.jda.api.entities.channel.concrete.Category; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; -import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; -import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.interactions.components.ActionRow; -import net.dv8tion.jda.api.interactions.components.text.TextInput; -import net.dv8tion.jda.api.interactions.components.text.TextInputStyle; -import net.dv8tion.jda.api.interactions.modals.Modal; - -import java.util.EnumSet; -import java.util.Objects; - -import static java.util.Optional.ofNullable; -import static java.util.concurrent.TimeUnit.SECONDS; -import static net.dv8tion.jda.api.Permission.VIEW_CHANNEL; -import static net.dv8tion.jda.api.entities.emoji.Emoji.fromUnicode; -import static net.dv8tion.jda.api.interactions.components.buttons.Button.danger; -import static net.dv8tion.jda.api.interactions.components.buttons.Button.secondary; -import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; -import static net.dv8tion.jda.api.interactions.components.text.TextInputStyle.PARAGRAPH; -import static net.dv8tion.jda.api.interactions.modals.Modal.create; -import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; -import static net.turniptales.discord.commands.GiveawayCommand.giveaways; -import static net.turniptales.discord.commands.SurveyCommand.pendingSurveys; - -public class ButtonInteractionListener extends ListenerAdapter { - - @Override - public void onButtonInteraction(ButtonInteractionEvent e) { - String componentId = e.getComponentId(); - Category ticketCategory = discordBotProperties.getTicketCategory(); - - switch (componentId) { - case "createTicketAddButton" -> { - Member member = e.getMember(); - assert member != null; - String memberId = member.getId(); - - boolean hasTicketChannel = ticketCategory.getChannels().stream() - .map(guildChannel -> discordBotProperties.getGuild().getTextChannelById(guildChannel.getId())) - .filter(Objects::nonNull) - .map(StandardGuildMessageChannel::getTopic) - .filter(Objects::nonNull) - .anyMatch(s -> s.contains(memberId)); - - if (hasTicketChannel) { - e.reply("Du hast bereits einen Ticket Channel!").setEphemeral(true).queue(); - return; - } - - TextInput minecraftNameTextInput = TextInput.create("minecraft_name_input", "Minecraft Name", TextInputStyle.SHORT) - .setMinLength(3) - .setMaxLength(16) - .setRequired(true) - .build(); - - TextInput logInput = TextInput.create("topic_input", "Anliegen", PARAGRAPH) - .setRequired(true) - .setPlaceholder("Hey, wie kann ich mich im Bauteam bewerben?") - .build(); - - Modal ticketModal = create("ticket_modal", "Neues Ticket") - .addComponents(ActionRow.of(minecraftNameTextInput), ActionRow.of(logInput)) - .build(); - - e.replyModal(ticketModal).queue(); - } - case "closeTicket" -> { - TextChannel textChannel = e.getChannel().asTextChannel(); - if (Objects.equals(textChannel.getParentCategory(), ticketCategory) && textChannel.getName().startsWith("ticket-")) { - e.reply("Möchtest Du das Ticket wirklich schließen?") - .addActionRow(danger("closeTicketConfirm", "Bestätigen"), secondary("closeTicketAbort", "Abbrechen")) - .queue(); - } - } - case "closeTicketConfirm" -> { - TextChannel textChannel = e.getChannel().asTextChannel(); - if (Objects.equals(textChannel.getParentCategory(), ticketCategory) && textChannel.getName().startsWith("ticket-")) { - textChannel.delete().queue(); - } - } - case "closeTicketAbort" -> e.getMessage().delete().queue(); - case "sendSurvey" -> { - Member member = e.getMember(); - assert member != null; - - ofNullable(pendingSurveys.remove(member)).ifPresentOrElse(survey -> { - discordBotProperties.getSurveyTextChannel().sendMessage("@everyone").setEmbeds(survey.toEmbed(member)) - .queue(message -> survey.getReactions().forEach(emoji -> message.addReaction(emoji).queue())); - - e.reply("Umfrage veröffentlicht!").setEphemeral(true).queue(); - e.getHook().deleteOriginal().queueAfter(5, SECONDS); - }, () -> { - e.reply("Es gibt keine Umfrage die veröffentlicht werden kann!").setEphemeral(true).queue(); - e.getHook().deleteOriginal().queueAfter(5, SECONDS); - }); - } - case "publishWinner" -> { - giveaways.get(e.getUser()).publishWinner(); - e.reply("Gewinner veröffentlicht!").setEphemeral(true).queue(); - e.getHook().deleteOriginal().queueAfter(5, SECONDS); - } - } - } - - @Override - public void onModalInteraction(ModalInteractionEvent e) { - String modalId = e.getModalId(); - - switch (modalId) { - case "ticket_modal" -> { - Member member = e.getMember(); - assert member != null; - String memberId = member.getId(); - String userName = member.getUser().getName(); - - String minecraftName = e.getValue("minecraft_name_input").getAsString(); - String log = e.getValue("topic_input").getAsString(); - - Role supporterRole = discordBotProperties.getSupporterRole(); - Role moderatorRole = discordBotProperties.getModeratorRole(); - discordBotProperties.getTicketCategory().createTextChannel("ticket-" + userName) - .setTopic("Ticket von " + userName + " (" + memberId + ")") - .addPermissionOverride(discordBotProperties.getGuild().getPublicRole(), null, EnumSet.of(VIEW_CHANNEL)) - .addPermissionOverride(member, EnumSet.of(VIEW_CHANNEL), null) - .addPermissionOverride(discordBotProperties.getSeniorModeratorRole(), EnumSet.of(VIEW_CHANNEL), null) - .addPermissionOverride(moderatorRole, EnumSet.of(VIEW_CHANNEL), null) - .addPermissionOverride(supporterRole, EnumSet.of(VIEW_CHANNEL), null) - .queue(textChannel -> textChannel - .sendMessage("Hey " + member.getAsMention() + "! Danke dass du ein Ticket erstellt hast. Die " + supporterRole.getAsMention() + " und " + moderatorRole.getAsMention() + " werden Dir schnellstmöglich deine Frage beantworten oder Dir helfen.\n" - + "Spieler: " + minecraftName + "\n" - + "Anliegen: " + log) - .addActionRow(success("closeTicket", "Ticket schließen").withEmoji(fromUnicode("U+1F512"))) - .queue(message -> e.reply("Du hast ein Ticket erstellt: " + message.getJumpUrl()).setEphemeral(true).queue())); - } - } - } -} From ca11e69b4a430666f59834cf75c3839f65d68c7b Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 19:54:08 +0200 Subject: [PATCH 51/58] Update messages and command registration, add MessageCommand --- .../discord/TurnipTalesDiscord.java | 37 ++++++++------ .../buttons/GiveawayWinnerPublishButton.java | 5 +- .../discord/commands/GiveawayCommand.java | 29 ++++++----- .../discord/commands/MessageCommand.java | 50 +++++++++++++++++++ .../discord/commands/RolesCommand.java | 4 +- .../discord/commands/StatsCommand.java | 4 +- .../discord/commands/TicketCommand.java | 32 ------------ 7 files changed, 92 insertions(+), 69 deletions(-) create mode 100644 src/main/java/net/turniptales/discord/commands/MessageCommand.java delete mode 100644 src/main/java/net/turniptales/discord/commands/TicketCommand.java diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index b7502f9..2db5a7c 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -5,6 +5,7 @@ import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; import net.dv8tion.jda.api.interactions.commands.build.Commands; +import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; import net.turniptales.discord.buttons.GiveawayWinnerPublishButton; import net.turniptales.discord.buttons.SyncButton; import net.turniptales.discord.buttons.TicketCloseAbortButton; @@ -12,11 +13,9 @@ import net.turniptales.discord.buttons.TicketCloseConfirmButton; import net.turniptales.discord.buttons.TicketCreateButton; import net.turniptales.discord.commands.GiveawayCommand; +import net.turniptales.discord.commands.MessageCommand; import net.turniptales.discord.commands.RolesCommand; import net.turniptales.discord.commands.StatsCommand; -import net.turniptales.discord.commands.TestCommand; -import net.turniptales.discord.commands.TicketCommand; -import net.turniptales.discord.commands.VerifyCommand; import net.turniptales.discord.common.api.Api; import net.turniptales.discord.common.configuration.DiscordBotProperties; import net.turniptales.discord.events.GuildAccessListener; @@ -30,6 +29,7 @@ import static java.lang.System.currentTimeMillis; import static java.time.ZoneId.of; import static net.dv8tion.jda.api.Permission.ADMINISTRATOR; +import static net.dv8tion.jda.api.Permission.VIEW_AUDIT_LOGS; import static net.dv8tion.jda.api.interactions.commands.OptionType.STRING; import static net.dv8tion.jda.api.interactions.commands.OptionType.USER; import static net.dv8tion.jda.api.requests.GatewayIntent.GUILD_MEMBERS; @@ -69,11 +69,10 @@ private static void startDiscordBot() throws InterruptedException { .enableIntents(MESSAGE_CONTENT) .enableIntents(GUILD_MEMBERS) .addEventListeners( - new GiveawayCommand(), - new RolesCommand(), - new StatsCommand(), - new TicketCommand(), - new VerifyCommand() + new GiveawayCommand("giveaway"), + new MessageCommand("nachricht"), + new RolesCommand("rollen"), + new StatsCommand("statistik") ) .addEventListeners( new GuildAccessListener() @@ -89,17 +88,23 @@ private static void startDiscordBot() throws InterruptedException { .build().awaitReady(); discordBotProperties.getGuild().updateCommands().addCommands( - Commands.slash("rollen", "Informationen zu den Rollen auf diesem Discord"), - Commands.slash("stats", "Deine Statistiken (nicht öffentlich) oder die eines Discord Nutzers (öffentlich)") - .addOption(USER, "player", "Discord Nutzer dessen Statistiken angezeigt werden sollen (Discord Nutzer muss sich verknüpft haben)", false), - Commands.slash("verify", "Verifiziert deinen Minecraft Account") - .addOption(STRING, "code", "Verifizierungscode", true), - - Commands.slash("ticket", "Erstellt die Nachricht um Tickets zu erstellen") + // only administrator + Commands.slash("nachricht", "Nachrichten Vorlagen") + .addSubcommands( + new SubcommandData("sync", "Nachrichten Vorlage für die Synchronisierung"), + new SubcommandData("ticket", "Nachrichten Vorlage für Tickets")) .setDefaultPermissions(DefaultMemberPermissions.enabledFor(ADMINISTRATOR)), + + // only supporter, moderator, senior-moderator Commands.slash("giveaway", "Lost einen Spieler anhand der Reaktionen einer Nachricht aus") .addOption(STRING, "message", "Nachricht mit den Reaktionen", true) - .setDefaultPermissions(DefaultMemberPermissions.enabledFor(ADMINISTRATOR)) + .setDefaultPermissions(DefaultMemberPermissions.enabledFor(VIEW_AUDIT_LOGS)), + Commands.slash("rollen", "Informationen zu den Rollen auf diesem Discord") + .setDefaultPermissions(DefaultMemberPermissions.enabledFor(VIEW_AUDIT_LOGS)), + + // everyone + Commands.slash("statistik", "Deine Statistiken (nicht öffentlich) oder die eines anderen Nutzers (öffentlich)") + .addOption(USER, "player", "Discord Nutzer dessen Statistiken angezeigt werden sollen (Discord Nutzer muss sich verknüpft haben)", false) ).queue(); } } diff --git a/src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java b/src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java index cfcefb4..bf34c32 100644 --- a/src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java +++ b/src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java @@ -2,6 +2,7 @@ import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import static java.lang.System.currentTimeMillis; import static java.util.concurrent.TimeUnit.SECONDS; import static net.turniptales.discord.commands.GiveawayCommand.giveaways; @@ -14,7 +15,7 @@ public GiveawayWinnerPublishButton() { @Override public void onButtonClick(ButtonInteractionEvent event) { giveaways.get(event.getUser()).publishWinner(); - event.reply("Gewinner veröffentlicht!").setEphemeral(true).queue(); - event.getHook().deleteOriginal().queueAfter(5, SECONDS); + event.reply("Gewinner veröffentlicht!\n-# 🚮 ").setEphemeral(true).queue(); + event.getHook().deleteOriginal().queueAfter(10, SECONDS); } } diff --git a/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java b/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java index 85c20cc..366b717 100644 --- a/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java +++ b/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java @@ -5,7 +5,6 @@ import net.dv8tion.jda.api.entities.MessageReaction; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import java.util.ArrayList; @@ -17,28 +16,28 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import static java.lang.System.currentTimeMillis; import static java.util.Objects.nonNull; import static java.util.concurrent.TimeUnit.SECONDS; -import static net.dv8tion.jda.api.Permission.ADMINISTRATOR; import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; @Log4j2 -public class GiveawayCommand extends ListenerAdapter { +public class GiveawayCommand extends CommandBase { public static final Map giveaways = new HashMap<>(); - @Override - public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { - if (!e.getName().equals("giveaway") || !Objects.requireNonNull(e.getMember()).hasPermission(ADMINISTRATOR)) { - return; - } + public GiveawayCommand(String name) { + super(name); + } - OptionMapping messageOptionMapping = e.getOption("message"); + @Override + public void onCommand(SlashCommandInteractionEvent event) { + OptionMapping messageOptionMapping = event.getOption("message"); if (nonNull(messageOptionMapping)) { - e.deferReply().setEphemeral(true).queue(); + event.deferReply().setEphemeral(true).queue(); - Message message = e.getChannel().retrieveMessageById(messageOptionMapping.getAsString()).complete(); + Message message = event.getChannel().retrieveMessageById(messageOptionMapping.getAsString()).complete(); List reactions = message.getReactions(); List usersWhoReacted = getUsersWhoReacted(reactions); @@ -51,15 +50,15 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent e) { .toList().get(new Random().nextInt(uniqueUsers.size())); Giveaway giveaway = new Giveaway(message, uniqueUsers, winner); - giveaways.put(e.getUser(), giveaway); + giveaways.put(event.getUser(), giveaway); - e.getHook() + event.getHook() .sendMessage("Reaktionen: " + usersWhoReacted.size() + " (" + reactions.size() + ")\nNutzer: " + uniqueUsers.size() + "\n\nGewinner: " + winner.getAsMention()) .addActionRow(success("publishWinner", "Gewinner veröffentlichen")) .queue(); } else { - e.reply("Es muss eine Nachrichten ID angegeben werden.").setEphemeral(true).queue(); - e.getHook().deleteOriginal().queueAfter(5, SECONDS); + event.reply("Es muss eine Nachrichten ID angegeben werden.\n-# 🚮 ").setEphemeral(true).queue(); + event.getHook().deleteOriginal().queueAfter(10, SECONDS); } } diff --git a/src/main/java/net/turniptales/discord/commands/MessageCommand.java b/src/main/java/net/turniptales/discord/commands/MessageCommand.java new file mode 100644 index 0000000..ebb88be --- /dev/null +++ b/src/main/java/net/turniptales/discord/commands/MessageCommand.java @@ -0,0 +1,50 @@ +package net.turniptales.discord.commands; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; + +import java.awt.Color; + +import static java.util.Objects.requireNonNull; +import static net.dv8tion.jda.api.entities.emoji.Emoji.fromUnicode; +import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; + +public class MessageCommand extends CommandBase { + + public MessageCommand(String name) { + super(name); + } + + @Override + public void onCommand(SlashCommandInteractionEvent event) { + event.deferReply(true).queue(); + + TextChannel textChannel = event.getChannel().asTextChannel(); + switch (requireNonNull(event.getSubcommandName())) { + case "sync" -> { + EmbedBuilder embedBuilder = new EmbedBuilder() + .setColor(new Color(0x609fee)) + .setTitle("Verifikation und Synchronisation") + .addField("🎡 **Du kannst Deinen Minecraft Account mit Deinem Discord Account verbinden! Dadurch hast Du unter anderem folgende Vorteile:**", "- Statistiken einsehen\n- Rechte synchronisieren\n- schnellerer und besserer Support", false); + + textChannel.sendMessageEmbeds(embedBuilder.build()) + .addActionRow(success("btn_sync", "Rechte synchronisieren").withEmoji(fromUnicode("U+1F504"))) + .queue(); + } + case "ticket" -> { + EmbedBuilder embedBuilder = new EmbedBuilder() + .setColor(new Color(0x609fee)) + .setTitle("Ticket") + .addField("🎫 **Hier kannst du ein Ticket erstellen um schnell Hilfe zu erhalten oder sonstige Fragen zu klären.**", "Bei der Erstellung eines Tickets wirst du nach deinem Minecraft Namen und Anliegen gefragt.", false); + + textChannel + .sendMessageEmbeds(embedBuilder.build()) + .addActionRow(success("btn_ticket_create", "Neues Ticket").withEmoji(fromUnicode("U+1F3AB"))) + .queue(); + } + } + + event.getHook().deleteOriginal().queue(); + } +} diff --git a/src/main/java/net/turniptales/discord/commands/RolesCommand.java b/src/main/java/net/turniptales/discord/commands/RolesCommand.java index b74f57a..bb06f56 100644 --- a/src/main/java/net/turniptales/discord/commands/RolesCommand.java +++ b/src/main/java/net/turniptales/discord/commands/RolesCommand.java @@ -6,8 +6,8 @@ public class RolesCommand extends CommandBase { - public RolesCommand() { - super("rollen"); + public RolesCommand(String name) { + super(name); } @Override diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index cced232..11210c0 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -31,8 +31,8 @@ public class StatsCommand extends CommandBase { public static final DecimalFormatSymbols US_SYMBOLS = DecimalFormatSymbols.getInstance(US); public static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("###.##", US_SYMBOLS); - public StatsCommand() { - super("stats"); + public StatsCommand(String name) { + super(name); } @Override diff --git a/src/main/java/net/turniptales/discord/commands/TicketCommand.java b/src/main/java/net/turniptales/discord/commands/TicketCommand.java deleted file mode 100644 index 61f97a1..0000000 --- a/src/main/java/net/turniptales/discord/commands/TicketCommand.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.turniptales.discord.commands; - -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; - -import java.awt.Color; - -import static net.dv8tion.jda.api.entities.emoji.Emoji.fromUnicode; -import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; -import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; - -public class TicketCommand extends CommandBase { - - public TicketCommand() { - super("ticket"); - } - - @Override - public void onCommand(SlashCommandInteractionEvent event) { - event.deferReply(true).queue(); - EmbedBuilder embedBuilder = new EmbedBuilder() - .setColor(new Color(0x609fee)) - .setTitle("Ticket") - .addField("🎫 **Hier kannst du ein Ticket erstellen um schnell Hilfe zu erhalten oder sonstige Fragen zu klären.**", "Bei der Erstellung eines Tickets wirst du nach deinem Minecraft Namen und Anliegen gefragt.", false); - - discordBotProperties.getTicketTextChannel() - .sendMessageEmbeds(embedBuilder.build()) - .addActionRow(success("createTicketAddButton", "Neues Ticket").withEmoji(fromUnicode("U+1F3AB"))) - .queue(); - event.getHook().deleteOriginal().queue(); - } -} From e34d59bdde91debf2b2bc0f70e156c41e288a9c1 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 21:40:06 +0200 Subject: [PATCH 52/58] Add self deleting message via UtilService --- .../buttons/GiveawayWinnerPublishButton.java | 6 ++---- .../discord/buttons/SyncButton.java | 12 ++++------- .../discord/commands/GiveawayCommand.java | 6 ++---- .../discord/commands/StatsCommand.java | 6 ++---- .../discord/common/services/UtilService.java | 21 +++++++++++++++++++ 5 files changed, 31 insertions(+), 20 deletions(-) create mode 100644 src/main/java/net/turniptales/discord/common/services/UtilService.java diff --git a/src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java b/src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java index bf34c32..8fa17dd 100644 --- a/src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java +++ b/src/main/java/net/turniptales/discord/buttons/GiveawayWinnerPublishButton.java @@ -2,9 +2,8 @@ import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; -import static java.lang.System.currentTimeMillis; -import static java.util.concurrent.TimeUnit.SECONDS; import static net.turniptales.discord.commands.GiveawayCommand.giveaways; +import static net.turniptales.discord.common.services.UtilService.sendSelfDeletingMessage; public class GiveawayWinnerPublishButton extends ButtonBase { @@ -15,7 +14,6 @@ public GiveawayWinnerPublishButton() { @Override public void onButtonClick(ButtonInteractionEvent event) { giveaways.get(event.getUser()).publishWinner(); - event.reply("Gewinner veröffentlicht!\n-# 🚮 ").setEphemeral(true).queue(); - event.getHook().deleteOriginal().queueAfter(10, SECONDS); + sendSelfDeletingMessage(event, "Gewinner veröffentlicht!"); } } diff --git a/src/main/java/net/turniptales/discord/buttons/SyncButton.java b/src/main/java/net/turniptales/discord/buttons/SyncButton.java index 50e65f4..9dfcad1 100644 --- a/src/main/java/net/turniptales/discord/buttons/SyncButton.java +++ b/src/main/java/net/turniptales/discord/buttons/SyncButton.java @@ -31,7 +31,7 @@ public SyncButton() { public void onButtonClick(ButtonInteractionEvent event) { User user = event.getUser(); if (currentTimeMillis() - this.lastSync.getOrDefault(user, 0L) <= SECONDS.toMillis(30)) { - event.reply("Du hast bereits vor weniger als 30 Sekunden deine Berechtigungen synchronisiert!").setEphemeral(true).queue(); + sendSelfDeletingMessage(event, "Du hast bereits vor weniger als 30 Sekunden deine Berechtigungen synchronisiert!"); return; } @@ -43,8 +43,7 @@ public void onButtonClick(ButtonInteractionEvent event) { if (connected) { synchronise(responseEntity.getBody()); - event.reply("Du hast deine Rechte synchronisiert.\n-# 🚮 ").setEphemeral(true).queue(); - event.getHook().deleteOriginal().queueAfter(10, SECONDS); + sendSelfDeletingMessage(event, "Du hast deine Rechte mit dem Minecraft Account " + connectionDataValue.getMinecraftName() + " synchronisiert!"); } else { event.replyModal(getVerificationModal()).queue(); } @@ -66,13 +65,10 @@ public void onModalInteraction(ModalInteractionEvent event) { if (success) { ConnectionDataValue connectionDataValue = api.getData(accountUserId).getBody(); synchronise(connectionDataValue); - message = "Du hast deinen Discord Account mit dem Minecraft Account " + connectionDataValue.getMinecraftName() + " verknüpft!"; + sendSelfDeletingMessage(event, "Du hast deine Rechte mit dem Minecraft Account " + connectionDataValue.getMinecraftName() + " synchronisiert!"); } else { - message = "Dein Discord Account konnte nicht mit deinem Minecraft Account verknüpft werden."; + sendSelfDeletingMessage(event, "Dein Discord Account konnte nicht mit deinem Minecraft Account verknüpft werden."); } - - event.reply(message + "\n-# 🚮 ").setEphemeral(true).queue(); - event.getHook().deleteOriginal().queueAfter(10, SECONDS); } private void synchronise(ConnectionDataValue connectionDataValue) { diff --git a/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java b/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java index 366b717..beae855 100644 --- a/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java +++ b/src/main/java/net/turniptales/discord/commands/GiveawayCommand.java @@ -16,10 +16,9 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import static java.lang.System.currentTimeMillis; import static java.util.Objects.nonNull; -import static java.util.concurrent.TimeUnit.SECONDS; import static net.dv8tion.jda.api.interactions.components.buttons.Button.success; +import static net.turniptales.discord.common.services.UtilService.sendSelfDeletingMessage; @Log4j2 public class GiveawayCommand extends CommandBase { @@ -57,8 +56,7 @@ public void onCommand(SlashCommandInteractionEvent event) { .addActionRow(success("publishWinner", "Gewinner veröffentlichen")) .queue(); } else { - event.reply("Es muss eine Nachrichten ID angegeben werden.\n-# 🚮 ").setEphemeral(true).queue(); - event.getHook().deleteOriginal().queueAfter(10, SECONDS); + sendSelfDeletingMessage(event, "Es muss eine Nachrichten-ID angegeben werden."); } } diff --git a/src/main/java/net/turniptales/discord/commands/StatsCommand.java b/src/main/java/net/turniptales/discord/commands/StatsCommand.java index 11210c0..5054f3a 100644 --- a/src/main/java/net/turniptales/discord/commands/StatsCommand.java +++ b/src/main/java/net/turniptales/discord/commands/StatsCommand.java @@ -19,12 +19,11 @@ import static java.awt.Color.CYAN; import static java.lang.String.valueOf; -import static java.lang.System.currentTimeMillis; import static java.util.Locale.US; import static java.util.Objects.nonNull; -import static java.util.concurrent.TimeUnit.SECONDS; import static net.turniptales.discord.TurnipTalesDiscord.api; import static net.turniptales.discord.TurnipTalesDiscord.discordBot; +import static net.turniptales.discord.common.services.UtilService.sendSelfDeletingMessage; public class StatsCommand extends CommandBase { @@ -48,8 +47,7 @@ public void onCommand(SlashCommandInteractionEvent event) { boolean isConnected = responseEntity.getStatusCode().is2xxSuccessful(); if (!isConnected) { - event.reply((notSelf ? "Der Spieler hat seinen" : "Du hast deinen") + " Discord Account noch nicht mit dem Minecraft Account verknüpft.\n-# 🚮 ").setEphemeral(true).queue(); - event.getHook().deleteOriginal().queueAfter(10, SECONDS); + sendSelfDeletingMessage(event, (notSelf ? "Der Spieler hat seinen" : "Du hast deinen") + " Discord Account noch nicht mit dem Minecraft Account verknüpft."); return; } diff --git a/src/main/java/net/turniptales/discord/common/services/UtilService.java b/src/main/java/net/turniptales/discord/common/services/UtilService.java new file mode 100644 index 0000000..fb134ce --- /dev/null +++ b/src/main/java/net/turniptales/discord/common/services/UtilService.java @@ -0,0 +1,21 @@ +package net.turniptales.discord.common.services; + +import net.dv8tion.jda.api.events.Event; +import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; + +import static java.lang.System.currentTimeMillis; +import static java.util.concurrent.TimeUnit.SECONDS; + +public class UtilService { + + public static void sendSelfDeletingMessage(Event event, String message) { + sendSelfDeletingMessage(event, message, 10); + } + + public static void sendSelfDeletingMessage(Event event, String message, int seconds) { + if (event instanceof IReplyCallback iReplyCallback) { + iReplyCallback.reply(message + "\n-# 🚮 ").setEphemeral(true).queue(); + iReplyCallback.getHook().deleteOriginal().queueAfter(seconds, SECONDS); + } + } +} From 35456042e15ea25ad6c045c97a01a2ccd0b46ff4 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 21:40:45 +0200 Subject: [PATCH 53/58] Remove logging for HTTP 4xx status --- .../java/net/turniptales/discord/common/api/Api.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/turniptales/discord/common/api/Api.java b/src/main/java/net/turniptales/discord/common/api/Api.java index d734517..8cc5085 100644 --- a/src/main/java/net/turniptales/discord/common/api/Api.java +++ b/src/main/java/net/turniptales/discord/common/api/Api.java @@ -9,6 +9,7 @@ import lombok.extern.log4j.Log4j2; import net.turniptales.discord.common.api.model.ConnectionDataValue; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClientResponseException; @@ -63,8 +64,13 @@ private ResponseEntity sendRequest(String url, HttpMethod method) { .onErrorResume(WebClientResponseException.class, ex -> { String responseBodyAsString = ex.getResponseBodyAsString(); String info = parseString(responseBodyAsString).getAsJsonObject().get("info").getAsString(); - log.error("Request failed with code {}: {}", ex.getStatusCode(), info); - return Mono.just(ResponseEntity.status(ex.getStatusCode()).body(responseBodyAsString)); + + HttpStatusCode statusCode = ex.getStatusCode(); + if (!statusCode.is4xxClientError()) { + log.error("Request failed with code {}: {}", statusCode, info); + } + + return Mono.just(ResponseEntity.status(statusCode).body(responseBodyAsString)); }) .block(); } From 23c0485c5b5b1810eb6d54e961dae8526d5ed794 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 21:42:29 +0200 Subject: [PATCH 54/58] Implement synchronizing for SyncButton and new SyncPermissionCommand --- .../discord/TurnipTalesDiscord.java | 15 ++++-- .../discord/buttons/SyncButton.java | 51 +++++++++++++++---- .../commands/SyncPermissionCommand.java | 31 +++++++++++ .../discord/commands/VerifyCommand.java | 41 --------------- .../configuration/DiscordBotProperties.java | 21 ++++++++ .../common/services/RoleSyncService.java | 37 +++++++------- src/main/resources/application.properties | 3 ++ 7 files changed, 125 insertions(+), 74 deletions(-) create mode 100644 src/main/java/net/turniptales/discord/commands/SyncPermissionCommand.java delete mode 100644 src/main/java/net/turniptales/discord/commands/VerifyCommand.java diff --git a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java index 2db5a7c..8662e14 100644 --- a/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java +++ b/src/main/java/net/turniptales/discord/TurnipTalesDiscord.java @@ -3,7 +3,6 @@ import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; -import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; import net.dv8tion.jda.api.interactions.commands.build.Commands; import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; import net.turniptales.discord.buttons.GiveawayWinnerPublishButton; @@ -16,6 +15,7 @@ import net.turniptales.discord.commands.MessageCommand; import net.turniptales.discord.commands.RolesCommand; import net.turniptales.discord.commands.StatsCommand; +import net.turniptales.discord.commands.SyncPermissionCommand; import net.turniptales.discord.common.api.Api; import net.turniptales.discord.common.configuration.DiscordBotProperties; import net.turniptales.discord.events.GuildAccessListener; @@ -30,6 +30,7 @@ import static java.time.ZoneId.of; import static net.dv8tion.jda.api.Permission.ADMINISTRATOR; import static net.dv8tion.jda.api.Permission.VIEW_AUDIT_LOGS; +import static net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions.enabledFor; import static net.dv8tion.jda.api.interactions.commands.OptionType.STRING; import static net.dv8tion.jda.api.interactions.commands.OptionType.USER; import static net.dv8tion.jda.api.requests.GatewayIntent.GUILD_MEMBERS; @@ -72,7 +73,8 @@ private static void startDiscordBot() throws InterruptedException { new GiveawayCommand("giveaway"), new MessageCommand("nachricht"), new RolesCommand("rollen"), - new StatsCommand("statistik") + new StatsCommand("statistik"), + new SyncPermissionCommand("synchronisieren") ) .addEventListeners( new GuildAccessListener() @@ -93,14 +95,17 @@ private static void startDiscordBot() throws InterruptedException { .addSubcommands( new SubcommandData("sync", "Nachrichten Vorlage für die Synchronisierung"), new SubcommandData("ticket", "Nachrichten Vorlage für Tickets")) - .setDefaultPermissions(DefaultMemberPermissions.enabledFor(ADMINISTRATOR)), + .setDefaultPermissions(enabledFor(ADMINISTRATOR)), // only supporter, moderator, senior-moderator Commands.slash("giveaway", "Lost einen Spieler anhand der Reaktionen einer Nachricht aus") .addOption(STRING, "message", "Nachricht mit den Reaktionen", true) - .setDefaultPermissions(DefaultMemberPermissions.enabledFor(VIEW_AUDIT_LOGS)), + .setDefaultPermissions(enabledFor(VIEW_AUDIT_LOGS)), Commands.slash("rollen", "Informationen zu den Rollen auf diesem Discord") - .setDefaultPermissions(DefaultMemberPermissions.enabledFor(VIEW_AUDIT_LOGS)), + .setDefaultPermissions(enabledFor(VIEW_AUDIT_LOGS)), + Commands.slash("synchronisieren", "Rechte eines Members synchronisieren") + .addOption(USER, "member", "Discord Nutzer dessen Rechte synchronisiert werden sollen (Discord Nutzer muss sich verknüpft haben)", true) + .setDefaultPermissions(enabledFor(VIEW_AUDIT_LOGS)), // everyone Commands.slash("statistik", "Deine Statistiken (nicht öffentlich) oder die eines anderen Nutzers (öffentlich)") diff --git a/src/main/java/net/turniptales/discord/buttons/SyncButton.java b/src/main/java/net/turniptales/discord/buttons/SyncButton.java index 9dfcad1..0961632 100644 --- a/src/main/java/net/turniptales/discord/buttons/SyncButton.java +++ b/src/main/java/net/turniptales/discord/buttons/SyncButton.java @@ -1,5 +1,7 @@ package net.turniptales.discord.buttons; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; @@ -18,6 +20,10 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static net.dv8tion.jda.api.interactions.modals.Modal.create; import static net.turniptales.discord.TurnipTalesDiscord.api; +import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; +import static net.turniptales.discord.common.services.RoleSyncService.getHighestTimeRole; +import static net.turniptales.discord.common.services.RoleSyncService.getTimeRoles; +import static net.turniptales.discord.common.services.UtilService.sendSelfDeletingMessage; public class SyncButton extends ButtonBase { @@ -35,15 +41,15 @@ public void onButtonClick(ButtonInteractionEvent event) { return; } - this.lastSync.put(user, currentTimeMillis()); - ResponseEntity responseEntity = api.getData(user.getId()); boolean connected = responseEntity.getStatusCode().is2xxSuccessful(); if (connected) { - synchronise(responseEntity.getBody()); + ConnectionDataValue connectionDataValue = responseEntity.getBody(); + synchronise(event.getMember(), requireNonNull(connectionDataValue)); sendSelfDeletingMessage(event, "Du hast deine Rechte mit dem Minecraft Account " + connectionDataValue.getMinecraftName() + " synchronisiert!"); + this.lastSync.put(user, currentTimeMillis()); } else { event.replyModal(getVerificationModal()).queue(); } @@ -56,23 +62,50 @@ public void onModalInteraction(ModalInteractionEvent event) { } String discordCode = requireNonNull(event.getValue("tip_discord_code")).getAsString(); - String accountUserId = event.getUser().getId(); + User user = event.getUser(); + String accountUserId = user.getId(); ResponseEntity response = api.connect(accountUserId, discordCode); - boolean success = response.getStatusCode().is2xxSuccessful(); + boolean success = response == null; - String message; if (success) { ConnectionDataValue connectionDataValue = api.getData(accountUserId).getBody(); - synchronise(connectionDataValue); + synchronise(event.getMember(), requireNonNull(connectionDataValue)); sendSelfDeletingMessage(event, "Du hast deine Rechte mit dem Minecraft Account " + connectionDataValue.getMinecraftName() + " synchronisiert!"); + this.lastSync.put(user, currentTimeMillis()); } else { sendSelfDeletingMessage(event, "Dein Discord Account konnte nicht mit deinem Minecraft Account verknüpft werden."); } } - private void synchronise(ConnectionDataValue connectionDataValue) { - System.out.println(connectionDataValue.getMinecraftName()); + public static void synchronise(Member member, ConnectionDataValue connectionDataValue) { + Guild guild = discordBotProperties.getGuild(); + + guild.removeRoleFromMember(member, discordBotProperties.getSeniorModeratorRole()).queue(); + guild.removeRoleFromMember(member, discordBotProperties.getModeratorRole()).queue(); + guild.removeRoleFromMember(member, discordBotProperties.getSupporterRole()).queue(); + guild.removeRoleFromMember(member, discordBotProperties.getTeamBuilderRole()).queue(); + guild.removeRoleFromMember(member, discordBotProperties.getTeamContentRole()).queue(); + guild.removeRoleFromMember(member, discordBotProperties.getTeamSocialMediaRole()).queue(); + getTimeRoles().forEach(role -> guild.removeRoleFromMember(member, role).queue()); + + guild.addRoleToMember(member, discordBotProperties.getPlayerRole()).queue(); + + switch (connectionDataValue.getRole()) { // ignore ADMINISTRATOR and HEAD_OF_DEVELOPMENT due to no permission + case "SENIOR_MODERATOR" -> guild.addRoleToMember(member, discordBotProperties.getSeniorModeratorRole()).queue(); + case "MODERATOR" -> guild.addRoleToMember(member, discordBotProperties.getModeratorRole()).queue(); + case "SUPPORTER" -> guild.addRoleToMember(member, discordBotProperties.getSupporterRole()).queue(); + } + + connectionDataValue.getTeams().forEach(teamName -> { + switch (teamName) { + case "BUILDER" -> guild.addRoleToMember(member, discordBotProperties.getTeamBuilderRole()).queue(); + case "CONTENT" -> guild.addRoleToMember(member, discordBotProperties.getTeamContentRole()).queue(); + case "SOCIAL_MEDIA" -> guild.addRoleToMember(member, discordBotProperties.getTeamSocialMediaRole()).queue(); + } + }); + + guild.addRoleToMember(member, getHighestTimeRole(requireNonNull(member).getTimeJoined())).queue(); } private Modal getVerificationModal() { diff --git a/src/main/java/net/turniptales/discord/commands/SyncPermissionCommand.java b/src/main/java/net/turniptales/discord/commands/SyncPermissionCommand.java new file mode 100644 index 0000000..686486a --- /dev/null +++ b/src/main/java/net/turniptales/discord/commands/SyncPermissionCommand.java @@ -0,0 +1,31 @@ +package net.turniptales.discord.commands; + +import lombok.extern.log4j.Log4j2; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.turniptales.discord.common.api.model.ConnectionDataValue; +import org.springframework.http.ResponseEntity; + +import static java.util.Objects.requireNonNull; +import static net.turniptales.discord.TurnipTalesDiscord.api; +import static net.turniptales.discord.buttons.SyncButton.synchronise; +import static net.turniptales.discord.common.services.UtilService.sendSelfDeletingMessage; + +@Log4j2 +public class SyncPermissionCommand extends CommandBase { + + public SyncPermissionCommand(String name) { + super(name); + } + + @Override + public void onCommand(SlashCommandInteractionEvent event) { + Member member = requireNonNull(event.getOption("member")).getAsMember(); + ResponseEntity connectionDataValueResponseEntity = api.getData(requireNonNull(member).getId()); + if (connectionDataValueResponseEntity.getStatusCode().is2xxSuccessful()) { + ConnectionDataValue connectionDataValue = connectionDataValueResponseEntity.getBody(); + synchronise(member, requireNonNull(connectionDataValue)); + sendSelfDeletingMessage(event, "Die Rechte für " + member.getEffectiveName() + " (" + connectionDataValue.getMinecraftName() + ") wurden synchronisiert!"); + } + } +} diff --git a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java b/src/main/java/net/turniptales/discord/commands/VerifyCommand.java deleted file mode 100644 index 1baceec..0000000 --- a/src/main/java/net/turniptales/discord/commands/VerifyCommand.java +++ /dev/null @@ -1,41 +0,0 @@ -package net.turniptales.discord.commands; - -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.interactions.commands.OptionMapping; -import net.turniptales.discord.common.api.model.ConnectionDataValue; -import org.springframework.http.ResponseEntity; - -import static java.util.Objects.isNull; -import static java.util.concurrent.TimeUnit.SECONDS; -import static net.turniptales.discord.TurnipTalesDiscord.api; - -public class VerifyCommand extends CommandBase { - - public VerifyCommand() { - super("verify"); - } - - @Override - public void onCommand(SlashCommandInteractionEvent event) { - OptionMapping codeOptionMapping = event.getOption("code"); - if (isNull(codeOptionMapping)) { - event.reply("Gib einen Verifizierungscode an!").setEphemeral(true).queue(); - return; - } - - String accountUserId = event.getUser().getId(); - ResponseEntity response = api.connect(accountUserId, codeOptionMapping.getAsString()); - boolean success = response.getStatusCode().is2xxSuccessful(); - - String message; - if (success) { - ConnectionDataValue connectionDataValue = api.getData(accountUserId); - message = "Du hast deinen Discord Account mit dem Minecraft Account " + connectionDataValue.getMinecraftName() + " verknüpft!"; - } else { - message = "Dein Discord Account konnte nicht mit deinem Minecraft Account verknüpft werden."; - } - - event.reply(message).setEphemeral(true).queue(); - event.getHook().deleteOriginal().queueAfter(5, SECONDS); - } -} diff --git a/src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java b/src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java index a55080d..b3b9a64 100644 --- a/src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java +++ b/src/main/java/net/turniptales/discord/common/configuration/DiscordBotProperties.java @@ -41,6 +41,15 @@ public class DiscordBotProperties { @Value("${discord.guild.roles.supporter-role}") private String supporterRole; + @Value("${discord.guild.roles.team-builder-role}") + private String teamBuilderRole; + + @Value("${discord.guild.roles.team-content-role}") + private String teamContentRole; + + @Value("${discord.guild.roles.team-social-media-role}") + private String teamSocialMediaRole; + @Value("${discord.guild.roles.role-0}") private String role0; @@ -100,6 +109,18 @@ public Role getSupporterRole() { return getGuild().getRoleById(this.supporterRole); } + public Role getTeamBuilderRole() { + return getGuild().getRoleById(this.teamBuilderRole); + } + + public Role getTeamContentRole() { + return getGuild().getRoleById(this.teamContentRole); + } + + public Role getTeamSocialMediaRole() { + return getGuild().getRoleById(this.teamSocialMediaRole); + } + public Role getRole0() { return getGuild().getRoleById(this.role0); } diff --git a/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java b/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java index 29623de..5687d2e 100644 --- a/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java +++ b/src/main/java/net/turniptales/discord/common/services/RoleSyncService.java @@ -14,39 +14,25 @@ import static java.lang.System.currentTimeMillis; import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.HOURS; +import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; @Log4j2 @Component public class RoleSyncService { - private final DiscordBotProperties discordBotProperties; - private List stayRoles; - public RoleSyncService(DiscordBotProperties discordBotProperties) { long sixHoursInMillis = HOURS.toMillis(6); new Timer().scheduleAtFixedRate(new TimerTask() { @Override public void run() { - RoleSyncService.this.stayRoles = List.of( - discordBotProperties.getRole0(), - discordBotProperties.getRole1Week(), - discordBotProperties.getRole2Week(), - discordBotProperties.getRole1Month(), - discordBotProperties.getRole3Month(), - discordBotProperties.getRole6Month(), - discordBotProperties.getRole1Year(), - discordBotProperties.getRole2Year(), - discordBotProperties.getRole3Year() - ); - long startTime = currentTimeMillis(); log.info("Discord role synchronising: started"); Guild guild = discordBotProperties.getGuild(); guild.loadMembers().get().forEach(member -> { - Role highestRoleUserShouldHave = getHighestRoleUserShouldHave(member.getTimeJoined()); - RoleSyncService.this.stayRoles.stream() + Role highestRoleUserShouldHave = getHighestTimeRole(member.getTimeJoined()); + getTimeRoles().stream() .filter(role -> !role.equals(highestRoleUserShouldHave)) .filter(role -> member.getRoles().contains(role)) .forEach(role -> { @@ -66,10 +52,23 @@ public void run() { } }, (sixHoursInMillis - currentTimeMillis() % sixHoursInMillis) + HOURS.toMillis(2), sixHoursInMillis); // 4 10 16 22 log.info("Discord role synchronising: scheduled"); - this.discordBotProperties = discordBotProperties; } - private Role getHighestRoleUserShouldHave(OffsetDateTime timeJoined) { + public static List getTimeRoles() { + return List.of( + discordBotProperties.getRole0(), + discordBotProperties.getRole1Week(), + discordBotProperties.getRole2Week(), + discordBotProperties.getRole1Month(), + discordBotProperties.getRole3Month(), + discordBotProperties.getRole6Month(), + discordBotProperties.getRole1Year(), + discordBotProperties.getRole2Year(), + discordBotProperties.getRole3Year() + ); + } + + public static Role getHighestTimeRole(OffsetDateTime timeJoined) { Role role = discordBotProperties.getRole0(); long joinTimeInMillis = timeJoined.toInstant().toEpochMilli(); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b0eb5a4..8a87e92 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -18,6 +18,9 @@ discord.guild.roles.player-role=1190675464549847110 discord.guild.roles.senior-moderator-role=1208149723547050004 discord.guild.roles.moderator-role=1025864289346658355 discord.guild.roles.supporter-role=1009477020427747408 +discord.guild.roles.team-builder-role=1169558449038831707 +discord.guild.roles.team-content-role=1234578921413148713 +discord.guild.roles.team-social-media-role=1191040099794833448 discord.guild.roles.role-0=1134487019058372649 discord.guild.roles.role-1-week=1134487221349650462 From 403b24c4dd28e5425371813d3006778da1103f19 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 22:02:39 +0200 Subject: [PATCH 55/58] Reformat code --- .../discord/buttons/SyncButton.java | 44 +------------ .../discord/commands/RolesCommand.java | 26 ++++---- .../commands/SyncPermissionCommand.java | 13 +--- .../discord/common/services/UtilService.java | 49 +++++++++++++++ .../discord/events/GuildAccessListener.java | 62 +++++++++---------- 5 files changed, 98 insertions(+), 96 deletions(-) diff --git a/src/main/java/net/turniptales/discord/buttons/SyncButton.java b/src/main/java/net/turniptales/discord/buttons/SyncButton.java index 0961632..bd3e83c 100644 --- a/src/main/java/net/turniptales/discord/buttons/SyncButton.java +++ b/src/main/java/net/turniptales/discord/buttons/SyncButton.java @@ -1,7 +1,5 @@ package net.turniptales.discord.buttons; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; @@ -20,10 +18,8 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static net.dv8tion.jda.api.interactions.modals.Modal.create; import static net.turniptales.discord.TurnipTalesDiscord.api; -import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; -import static net.turniptales.discord.common.services.RoleSyncService.getHighestTimeRole; -import static net.turniptales.discord.common.services.RoleSyncService.getTimeRoles; import static net.turniptales.discord.common.services.UtilService.sendSelfDeletingMessage; +import static net.turniptales.discord.common.services.UtilService.synchronise; public class SyncButton extends ButtonBase { @@ -46,9 +42,7 @@ public void onButtonClick(ButtonInteractionEvent event) { boolean connected = responseEntity.getStatusCode().is2xxSuccessful(); if (connected) { - ConnectionDataValue connectionDataValue = responseEntity.getBody(); - synchronise(event.getMember(), requireNonNull(connectionDataValue)); - sendSelfDeletingMessage(event, "Du hast deine Rechte mit dem Minecraft Account " + connectionDataValue.getMinecraftName() + " synchronisiert!"); + synchronise(event, requireNonNull(event.getMember())); this.lastSync.put(user, currentTimeMillis()); } else { event.replyModal(getVerificationModal()).queue(); @@ -69,45 +63,13 @@ public void onModalInteraction(ModalInteractionEvent event) { boolean success = response == null; if (success) { - ConnectionDataValue connectionDataValue = api.getData(accountUserId).getBody(); - synchronise(event.getMember(), requireNonNull(connectionDataValue)); - sendSelfDeletingMessage(event, "Du hast deine Rechte mit dem Minecraft Account " + connectionDataValue.getMinecraftName() + " synchronisiert!"); + synchronise(event, requireNonNull(event.getMember())); this.lastSync.put(user, currentTimeMillis()); } else { sendSelfDeletingMessage(event, "Dein Discord Account konnte nicht mit deinem Minecraft Account verknüpft werden."); } } - public static void synchronise(Member member, ConnectionDataValue connectionDataValue) { - Guild guild = discordBotProperties.getGuild(); - - guild.removeRoleFromMember(member, discordBotProperties.getSeniorModeratorRole()).queue(); - guild.removeRoleFromMember(member, discordBotProperties.getModeratorRole()).queue(); - guild.removeRoleFromMember(member, discordBotProperties.getSupporterRole()).queue(); - guild.removeRoleFromMember(member, discordBotProperties.getTeamBuilderRole()).queue(); - guild.removeRoleFromMember(member, discordBotProperties.getTeamContentRole()).queue(); - guild.removeRoleFromMember(member, discordBotProperties.getTeamSocialMediaRole()).queue(); - getTimeRoles().forEach(role -> guild.removeRoleFromMember(member, role).queue()); - - guild.addRoleToMember(member, discordBotProperties.getPlayerRole()).queue(); - - switch (connectionDataValue.getRole()) { // ignore ADMINISTRATOR and HEAD_OF_DEVELOPMENT due to no permission - case "SENIOR_MODERATOR" -> guild.addRoleToMember(member, discordBotProperties.getSeniorModeratorRole()).queue(); - case "MODERATOR" -> guild.addRoleToMember(member, discordBotProperties.getModeratorRole()).queue(); - case "SUPPORTER" -> guild.addRoleToMember(member, discordBotProperties.getSupporterRole()).queue(); - } - - connectionDataValue.getTeams().forEach(teamName -> { - switch (teamName) { - case "BUILDER" -> guild.addRoleToMember(member, discordBotProperties.getTeamBuilderRole()).queue(); - case "CONTENT" -> guild.addRoleToMember(member, discordBotProperties.getTeamContentRole()).queue(); - case "SOCIAL_MEDIA" -> guild.addRoleToMember(member, discordBotProperties.getTeamSocialMediaRole()).queue(); - } - }); - - guild.addRoleToMember(member, getHighestTimeRole(requireNonNull(member).getTimeJoined())).queue(); - } - private Modal getVerificationModal() { TextInput discordCodeInput = TextInput.create("tip_discord_code", "Discord Code", TextInputStyle.SHORT) .setMinLength(8) diff --git a/src/main/java/net/turniptales/discord/commands/RolesCommand.java b/src/main/java/net/turniptales/discord/commands/RolesCommand.java index bb06f56..423701b 100644 --- a/src/main/java/net/turniptales/discord/commands/RolesCommand.java +++ b/src/main/java/net/turniptales/discord/commands/RolesCommand.java @@ -14,9 +14,9 @@ public RolesCommand(String name) { public void onCommand(SlashCommandInteractionEvent event) { event.reply(""" Die Standard Rolle für jedes Mitglied ist `%s`. - + Wenn man längere Zeit auf diesem Discord ist, wird einem automatisch eine Rolle zugewiesen. Je nachdem, wie lang man schon auf diesem Discord ist, erhält man eine höhere Rolle: - + `%s` ➜ direkt nach Serverbeitritt `%s` ➜ nach einer Woche `%s` ➜ nach zwei Wochen @@ -26,18 +26,18 @@ public void onCommand(SlashCommandInteractionEvent event) { `%s` ➜ nach einem Jahr `%s` ➜ nach zwei Jahren `%s` ➜ nach drei Jahren - + So sieht man auch gut, wer schon lang dabei ist und sich schon gut auskennen könnte. Die Rollen werden durch den TurnipTales Bot automatisch vergeben und können dadurch nicht erstattet werden, wenn man den Server zwischenzeitlich verlässt. """.formatted( - discordBotProperties.getPlayerRole().getName(), - discordBotProperties.getRole0().getName(), - discordBotProperties.getRole1Week().getName(), - discordBotProperties.getRole2Week().getName(), - discordBotProperties.getRole1Month().getName(), - discordBotProperties.getRole3Month().getName(), - discordBotProperties.getRole6Month().getName(), - discordBotProperties.getRole1Year().getName(), - discordBotProperties.getRole2Year().getName(), - discordBotProperties.getRole3Year().getName())).queue(); + discordBotProperties.getPlayerRole().getName(), + discordBotProperties.getRole0().getName(), + discordBotProperties.getRole1Week().getName(), + discordBotProperties.getRole2Week().getName(), + discordBotProperties.getRole1Month().getName(), + discordBotProperties.getRole3Month().getName(), + discordBotProperties.getRole6Month().getName(), + discordBotProperties.getRole1Year().getName(), + discordBotProperties.getRole2Year().getName(), + discordBotProperties.getRole3Year().getName())).queue(); } } diff --git a/src/main/java/net/turniptales/discord/commands/SyncPermissionCommand.java b/src/main/java/net/turniptales/discord/commands/SyncPermissionCommand.java index 686486a..c3126bc 100644 --- a/src/main/java/net/turniptales/discord/commands/SyncPermissionCommand.java +++ b/src/main/java/net/turniptales/discord/commands/SyncPermissionCommand.java @@ -3,13 +3,9 @@ import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.turniptales.discord.common.api.model.ConnectionDataValue; -import org.springframework.http.ResponseEntity; import static java.util.Objects.requireNonNull; -import static net.turniptales.discord.TurnipTalesDiscord.api; -import static net.turniptales.discord.buttons.SyncButton.synchronise; -import static net.turniptales.discord.common.services.UtilService.sendSelfDeletingMessage; +import static net.turniptales.discord.common.services.UtilService.synchronise; @Log4j2 public class SyncPermissionCommand extends CommandBase { @@ -21,11 +17,6 @@ public SyncPermissionCommand(String name) { @Override public void onCommand(SlashCommandInteractionEvent event) { Member member = requireNonNull(event.getOption("member")).getAsMember(); - ResponseEntity connectionDataValueResponseEntity = api.getData(requireNonNull(member).getId()); - if (connectionDataValueResponseEntity.getStatusCode().is2xxSuccessful()) { - ConnectionDataValue connectionDataValue = connectionDataValueResponseEntity.getBody(); - synchronise(member, requireNonNull(connectionDataValue)); - sendSelfDeletingMessage(event, "Die Rechte für " + member.getEffectiveName() + " (" + connectionDataValue.getMinecraftName() + ") wurden synchronisiert!"); - } + synchronise(event, requireNonNull(member)); } } diff --git a/src/main/java/net/turniptales/discord/common/services/UtilService.java b/src/main/java/net/turniptales/discord/common/services/UtilService.java index fb134ce..28c0d96 100644 --- a/src/main/java/net/turniptales/discord/common/services/UtilService.java +++ b/src/main/java/net/turniptales/discord/common/services/UtilService.java @@ -1,10 +1,19 @@ package net.turniptales.discord.common.services; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.events.Event; import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; +import net.turniptales.discord.common.api.model.ConnectionDataValue; +import org.springframework.http.ResponseEntity; import static java.lang.System.currentTimeMillis; +import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.SECONDS; +import static net.turniptales.discord.TurnipTalesDiscord.api; +import static net.turniptales.discord.TurnipTalesDiscord.discordBotProperties; +import static net.turniptales.discord.common.services.RoleSyncService.getHighestTimeRole; +import static net.turniptales.discord.common.services.RoleSyncService.getTimeRoles; public class UtilService { @@ -18,4 +27,44 @@ public static void sendSelfDeletingMessage(Event event, String message, int seco iReplyCallback.getHook().deleteOriginal().queueAfter(seconds, SECONDS); } } + + public static void synchronise(Event event, Member member) { + ResponseEntity connectionDataValueResponseEntity = api.getData(member.getId()); + if (!connectionDataValueResponseEntity.getStatusCode().is2xxSuccessful()) { + return; + } + + ConnectionDataValue connectionDataValue = connectionDataValueResponseEntity.getBody(); + Guild guild = discordBotProperties.getGuild(); + + guild.removeRoleFromMember(member, discordBotProperties.getSeniorModeratorRole()).queue(); + guild.removeRoleFromMember(member, discordBotProperties.getModeratorRole()).queue(); + guild.removeRoleFromMember(member, discordBotProperties.getSupporterRole()).queue(); + guild.removeRoleFromMember(member, discordBotProperties.getTeamBuilderRole()).queue(); + guild.removeRoleFromMember(member, discordBotProperties.getTeamContentRole()).queue(); + guild.removeRoleFromMember(member, discordBotProperties.getTeamSocialMediaRole()).queue(); + getTimeRoles().forEach(role -> guild.removeRoleFromMember(member, role).queue()); + + guild.addRoleToMember(member, discordBotProperties.getPlayerRole()).queue(); + + // ignore ADMINISTRATOR and HEAD_OF_DEVELOPMENT due to no permission + // ignore DEVELOPER due to not overwrite support-roles + switch (requireNonNull(connectionDataValue).getRole()) { + case "SENIOR_MODERATOR" -> guild.addRoleToMember(member, discordBotProperties.getSeniorModeratorRole()).queue(); + case "MODERATOR" -> guild.addRoleToMember(member, discordBotProperties.getModeratorRole()).queue(); + case "SUPPORTER" -> guild.addRoleToMember(member, discordBotProperties.getSupporterRole()).queue(); + } + + connectionDataValue.getTeams().forEach(teamName -> { + switch (teamName) { + case "BUILDER" -> guild.addRoleToMember(member, discordBotProperties.getTeamBuilderRole()).queue(); + case "CONTENT" -> guild.addRoleToMember(member, discordBotProperties.getTeamContentRole()).queue(); + case "SOCIAL_MEDIA" -> guild.addRoleToMember(member, discordBotProperties.getTeamSocialMediaRole()).queue(); + } + }); + + guild.addRoleToMember(member, getHighestTimeRole(requireNonNull(member).getTimeJoined())).queue(); + + sendSelfDeletingMessage(event, "Rechte synchronisiert mit Minecraft Account `" + connectionDataValue.getMinecraftName() + "` für: " + member.getAsMention()); + } } diff --git a/src/main/java/net/turniptales/discord/events/GuildAccessListener.java b/src/main/java/net/turniptales/discord/events/GuildAccessListener.java index 1d6161a..d7f14c6 100644 --- a/src/main/java/net/turniptales/discord/events/GuildAccessListener.java +++ b/src/main/java/net/turniptales/discord/events/GuildAccessListener.java @@ -20,37 +20,6 @@ public class GuildAccessListener extends ListenerAdapter { - @Override - public void onGuildMemberJoin(GuildMemberJoinEvent e) { - Guild guild = e.getGuild(); - TextChannel communityTextChannel = discordBotProperties.getCommunityTextChannel(); - TextChannel missionControlTextChannel = guild.getSystemChannel(); - if (nonNull(communityTextChannel) && nonNull(missionControlTextChannel)) { - Member member = e.getMember(); - - EmbedBuilder embedBuildercommunityTextChannel = new EmbedBuilder() - .setColor(CYAN) - .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) - .setTitle("Willkommen auf TurnipTales!") - .setDescription(member.getAsMention() + " hat den Server betreten.") - .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), member.getEffectiveAvatarUrl()) - .setTimestamp(new Date().toInstant()); - - EmbedBuilder embedBuildermissionControlTextChannel = new EmbedBuilder() - .setColor(CYAN) - .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) - .setDescription(member.getAsMention() + " hat den Server betreten.") - .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), member.getEffectiveAvatarUrl()) - .setTimestamp(new Date().toInstant()); - - communityTextChannel.sendMessageEmbeds(embedBuildercommunityTextChannel.build()).queue(); - missionControlTextChannel.sendMessageEmbeds(embedBuildermissionControlTextChannel.build()).queue(); - - guild.addRoleToMember(e.getUser(), discordBotProperties.getPlayerRole()).queue(); - guild.addRoleToMember(e.getUser(), discordBotProperties.getRole0()).queue(); - } - } - @Override public void onGuildBan(GuildBanEvent e) { Guild guild = e.getGuild(); @@ -95,4 +64,35 @@ public void onGuildMemberRemove(GuildMemberRemoveEvent e) { missionControlTextChannel.sendMessageEmbeds(embedBuilder.build()).queue(); } } + + @Override + public void onGuildMemberJoin(GuildMemberJoinEvent e) { + Guild guild = e.getGuild(); + TextChannel communityTextChannel = discordBotProperties.getCommunityTextChannel(); + TextChannel missionControlTextChannel = guild.getSystemChannel(); + if (nonNull(communityTextChannel) && nonNull(missionControlTextChannel)) { + Member member = e.getMember(); + + EmbedBuilder embedBuildercommunityTextChannel = new EmbedBuilder() + .setColor(CYAN) + .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) + .setTitle("Willkommen auf TurnipTales!") + .setDescription(member.getAsMention() + " hat den Server betreten.") + .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), member.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + EmbedBuilder embedBuildermissionControlTextChannel = new EmbedBuilder() + .setColor(CYAN) + .setAuthor("TurnipTales", "https://turniptales.net/", discordBot.getSelfUser().getEffectiveAvatarUrl()) + .setDescription(member.getAsMention() + " hat den Server betreten.") + .setFooter("Aktuelle Spieler: " + guild.getMemberCount(), member.getEffectiveAvatarUrl()) + .setTimestamp(new Date().toInstant()); + + communityTextChannel.sendMessageEmbeds(embedBuildercommunityTextChannel.build()).queue(); + missionControlTextChannel.sendMessageEmbeds(embedBuildermissionControlTextChannel.build()).queue(); + + guild.addRoleToMember(e.getUser(), discordBotProperties.getPlayerRole()).queue(); + guild.addRoleToMember(e.getUser(), discordBotProperties.getRole0()).queue(); + } + } } From 69e6a9e1153b7ad43534b3ecfa9dd5b103022ca2 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 22:03:46 +0200 Subject: [PATCH 56/58] Clean up code --- .../java/net/turniptales/discord/buttons/SyncButton.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/net/turniptales/discord/buttons/SyncButton.java b/src/main/java/net/turniptales/discord/buttons/SyncButton.java index bd3e83c..08f7430 100644 --- a/src/main/java/net/turniptales/discord/buttons/SyncButton.java +++ b/src/main/java/net/turniptales/discord/buttons/SyncButton.java @@ -7,7 +7,6 @@ import net.dv8tion.jda.api.interactions.components.text.TextInput; import net.dv8tion.jda.api.interactions.components.text.TextInputStyle; import net.dv8tion.jda.api.interactions.modals.Modal; -import net.turniptales.discord.common.api.model.ConnectionDataValue; import org.springframework.http.ResponseEntity; import java.util.HashMap; @@ -37,11 +36,7 @@ public void onButtonClick(ButtonInteractionEvent event) { return; } - ResponseEntity responseEntity = api.getData(user.getId()); - - boolean connected = responseEntity.getStatusCode().is2xxSuccessful(); - - if (connected) { + if (api.getData(user.getId()).getStatusCode().is2xxSuccessful()) { synchronise(event, requireNonNull(event.getMember())); this.lastSync.put(user, currentTimeMillis()); } else { From 0f7f7f9e10793ebb7437c6234b33611ca273ff2a Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 22:20:31 +0200 Subject: [PATCH 57/58] Update GitHub actions with auto deploy and secret providing --- .github/workflows/build.yml | 31 ++++++++++--- .github/workflows/release.yml | 53 ++++++++++++++++++----- pom.xml | 5 +-- src/main/resources/application.properties | 3 +- 4 files changed, 71 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca52dad..bd17a6c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,21 +1,38 @@ name: Build on: + push: + branches: [ "develop", "hotfix/**" ] pull_request: - branches: - - main - - develop + branches: [ "develop", "hotfix/**" ] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: build: + + name: 🏗️ Build TurnipTales Discord Bot runs-on: ubuntu-latest + steps: - uses: actions/checkout@v4 - - name: Set up JDK 17 + with: + fetch-depth: 0 + + - name: Set up JDK 21 uses: actions/setup-java@v4 with: - distribution: 'corretto' - java-version: '17' + java-version: '21' + distribution: 'temurin' cache: maven + + - name: Set application properties + env: + DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }} + run: | + echo "discord.bot.token=$DISCORD_BOT_TOKEN" >> src/main/resources/application.properties + - name: Build with Maven - run: mvn -B package --file pom.xml \ No newline at end of file + run: mvn -B test package --file pom.xml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 10a729a..1bc6b72 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,24 +2,57 @@ name: Release on: push: - branches: - - main + branches: [ "main" ] jobs: release: + + name: 🎉 Release TurnipTales Discord Bot runs-on: ubuntu-latest + steps: - uses: actions/checkout@v4 - - name: Set up JDK 17 + with: + fetch-depth: 0 + + - name: Set up JDK 21 uses: actions/setup-java@v4 with: - distribution: 'corretto' - java-version: '17' + java-version: '21' + distribution: 'temurin' cache: maven + + - name: Set application properties + env: + DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }} + run: | + echo "discord.bot.token=$DISCORD_BOT_TOKEN" >> src/main/resources/application.properties + - name: Build with Maven - run: mvn -B package --file pom.xml - - name: Upload Artifact - uses: actions/upload-artifact@v4 + run: mvn -B test package --file pom.xml + + - if: github.event_name == 'push' + name: Upload via SCP + uses: appleboy/scp-action@v0.1.7 + with: + host: turniptales.net + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + port: 22 + source: "target/turniptales-discord.jar" + target: "/home/discord" + timeout: 120s + strip_components: 1 + + - if: github.event_name == 'push' + name: Restart TurnipTales API + uses: appleboy/ssh-action@v1.0.3 with: - name: Artifacts - path: target/turniptales-discord.jar \ No newline at end of file + host: turniptales.net + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + port: 22 + script: | + cd /home/discord + chown -R root:root turniptales-discord.jar + ./run.sh diff --git a/pom.xml b/pom.xml index 108d10b..0e87cfc 100644 --- a/pom.xml +++ b/pom.xml @@ -18,8 +18,8 @@ Discord application of TurnipTales - 17 - 17 + 21 + 21 UTF-8 @@ -84,5 +84,4 @@ - diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8a87e92..694637b 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -6,7 +6,6 @@ server.error.whitelabel.enabled=false spring.main.banner-mode=off spring.output.ansi.enabled=ALWAYS -discord.bot.token=MTE5MDcxNDY0MzU1MTg5MTQ3OA.GdvTJE.EMI9oOxjzEe-unfAXWPtOKgb2qGtWkqonPq5OY discord.guild.id=1008928645185810463 discord.guild.channels.community-text-channel=1008929885764472952 @@ -31,3 +30,5 @@ discord.guild.roles.role-6-month=1134487539588268094 discord.guild.roles.role-1-year=1134487593585745920 discord.guild.roles.role-2-year=1134487644110336010 discord.guild.roles.role-3-year=1134487702864142356 + +# Discord Bot Token generated by GitHub Action From 44163218773379377f863b32bee25df74ab4ff35 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 16 Jul 2024 22:23:17 +0200 Subject: [PATCH 58/58] Remove unused Dockerfile --- Dockerfile | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index a901423..0000000 --- a/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM openjdk:24 - -WORKDIR /app - -COPY turniptales-discord.jar /app/turniptales-discord.jar - -CMD ["java", "-jar", "turniptales-discord.jar"] \ No newline at end of file