diff --git a/src/main/java/eu/mhsl/craftattack/spawn/api/client/HttpRepository.java b/src/main/java/eu/mhsl/craftattack/spawn/api/client/HttpRepository.java index 963c3a0..0f66ef4 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/api/client/HttpRepository.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/api/client/HttpRepository.java @@ -74,6 +74,7 @@ public abstract class HttpRepository extends Repository { private ReqResp sendHttp(HttpRequest request) { try(HttpClient client = HttpClient.newHttpClient()) { + this.validateThread(); HttpResponse httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); return new ReqResp<>(httpResponse.statusCode(), httpResponse.body()); } catch(IOException | InterruptedException e) { diff --git a/src/main/java/eu/mhsl/craftattack/spawn/api/client/Repository.java b/src/main/java/eu/mhsl/craftattack/spawn/api/client/Repository.java index 9250ece..d51a943 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/api/client/Repository.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/api/client/Repository.java @@ -1,6 +1,8 @@ package eu.mhsl.craftattack.spawn.api.client; import com.google.gson.Gson; +import eu.mhsl.craftattack.spawn.Main; +import org.bukkit.Bukkit; import java.net.URI; @@ -12,4 +14,8 @@ public abstract class Repository { this.basePath = basePath; this.gson = new Gson(); } + + protected void validateThread() { + if(Bukkit.isPrimaryThread()) Main.logger().warning("Repository was called synchronously!"); + } } diff --git a/src/main/java/eu/mhsl/craftattack/spawn/api/client/repositories/ReportRepository.java b/src/main/java/eu/mhsl/craftattack/spawn/api/client/repositories/ReportRepository.java index 7da116d..c967e12 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/api/client/repositories/ReportRepository.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/api/client/repositories/ReportRepository.java @@ -2,7 +2,6 @@ package eu.mhsl.craftattack.spawn.api.client.repositories; import eu.mhsl.craftattack.spawn.api.client.HttpRepository; import eu.mhsl.craftattack.spawn.api.client.ReqResp; -import eu.mhsl.craftattack.spawn.appliances.report.Report; import eu.mhsl.craftattack.spawn.util.api.ApiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,22 +14,44 @@ public class ReportRepository extends HttpRepository { super(ApiUtil.getBaseUri(), ApiUtil::withAuthorizationSecret); } - public record ReportData(@NotNull UUID reporter, @Nullable UUID reported, String reason) { + public record ReportCreationInfo(@NotNull UUID reporter, @Nullable UUID reported, String reason) { } - public record ReportDataResponse(@NotNull String url) { + public record ReportUrl(@NotNull String url) { } - public record ReportsResponse(List from_self, Object to_self) { + public record PlayerReports( + List from_self, + Object to_self + ) { + public record Report( + @Nullable Reporter reported, + @NotNull String subject, + boolean draft, + @NotNull String status, + @NotNull String url + ) { + public record Reporter( + @NotNull String username, + @NotNull String uuid + ) { + } + } } - public record ReportInfo(Reporter reported, @NotNull String subject, boolean draft, @NotNull String status, @NotNull String url) { + public ReqResp queryReports(UUID player) { + return this.get( + "report", + (parameters) -> parameters.addParameter("uuid", player.toString()), + PlayerReports.class + ); } - public record Reporter(@NotNull String username, @NotNull String uuid) { - } - - public ReqResp queryReports(UUID player) { - return this.get("reports", (builder) -> builder.addParameter("token", "asd"), input, SendReportResponse.class); + public ReqResp createReport(ReportCreationInfo data) { + return this.post( + "report", + data, + ReportUrl.class + ); } } diff --git a/src/main/java/eu/mhsl/craftattack/spawn/api/client/repositories/WhitelistRepository.java b/src/main/java/eu/mhsl/craftattack/spawn/api/client/repositories/WhitelistRepository.java index f0830b0..414e1b3 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/api/client/repositories/WhitelistRepository.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/api/client/repositories/WhitelistRepository.java @@ -18,12 +18,13 @@ public class WhitelistRepository extends HttpRepository { String lastname, Long banned_until, Long outlawed_until - ) {} + ) { + } public ReqResp getUserData(UUID userId) { return this.get( "user", - uriBuilder -> uriBuilder.addParameter("uuid", userId.toString()), + parameters -> parameters.addParameter("uuid", userId.toString()), UserData.class ); } diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/report/Report.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/report/Report.java index c426c95..d35aac4 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/report/Report.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/report/Report.java @@ -1,7 +1,8 @@ package eu.mhsl.craftattack.spawn.appliances.report; -import com.google.gson.Gson; import eu.mhsl.craftattack.spawn.Main; +import eu.mhsl.craftattack.spawn.api.client.ReqResp; +import eu.mhsl.craftattack.spawn.api.client.repositories.ReportRepository; import eu.mhsl.craftattack.spawn.appliance.Appliance; import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; import net.kyori.adventure.text.Component; @@ -10,22 +11,14 @@ import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.format.NamedTextColor; -import org.apache.http.client.utils.URIBuilder; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; import java.util.List; import java.util.Optional; -import java.util.UUID; public class Report extends Appliance { public static Component helpText() { @@ -38,163 +31,51 @@ public class Report extends Appliance { .build(); } - private URI apiEndpoint; - private String apiSecret; - public Report() { super("report"); } - private record Request(@NotNull UUID reporter, @Nullable UUID reported, String reason) { - } - - private record ReportResponse(@NotNull String url) { - } - - private record ReportsResponse(List from_self, Object to_self) { - } - - private record ReportInfo(Reporter reported, @NotNull String subject, boolean draft, @NotNull String status, @NotNull String url) { - } - - private record Reporter(@NotNull String username, @NotNull String uuid) { - } - public void reportToUnknown(@NotNull Player issuer) { - Request request = new Request(issuer.getUniqueId(), null, ""); - this.issueReport(issuer, request); + ReportRepository.ReportCreationInfo request = new ReportRepository.ReportCreationInfo(issuer.getUniqueId(), null, ""); + this.createReport(issuer, request); } public void reportToKnown(@NotNull Player issuer, @NotNull String targetUsername, @Nullable String reason) { OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(targetUsername); if(issuer.getUniqueId().equals(offlinePlayer.getUniqueId())) { - issuer.sendMessage( - Component.text("Du kannst dich nicht selbst reporten.").color(NamedTextColor.RED) - ); + issuer.sendMessage(Component.text("Du kannst dich nicht selbst reporten.", NamedTextColor.RED)); return; } - Request request = new Request(issuer.getUniqueId(), offlinePlayer.getUniqueId(), Optional.ofNullable(reason).orElse("")); - this.issueReport(issuer, request); - } - - public void requestReports(Player issuer) { - URIBuilder uriBuilder = new URIBuilder(this.apiEndpoint); - uriBuilder.addParameter("secret", apiSecret); - uriBuilder.addParameter("uuid", issuer.getUniqueId().toString()); - - try(HttpClient client = HttpClient.newHttpClient()) { - HttpRequest httpRequest = HttpRequest.newBuilder() - .uri(uriBuilder.build()) - .header("Content-Type", "application/json") - .GET() - .build(); - - HttpResponse httpResponse = client.send(httpRequest, HttpResponse.BodyHandlers.ofString()); - this.printReports(issuer, httpResponse); - } catch (IOException | InterruptedException | URISyntaxException e) { - issuer.sendMessage( - Component.text("Internal server description: " + e.getMessage()).color(NamedTextColor.RED) - ); - throw new RuntimeException(e); - } - } - - private void issueReport(Player issuer, Request reportRequest) { - URIBuilder uriBuilder = new URIBuilder(this.apiEndpoint); - uriBuilder.addParameter("secret", apiSecret); - - try(HttpClient client = HttpClient.newHttpClient()) { - HttpRequest httpRequest = HttpRequest.newBuilder() - .uri(uriBuilder.build()) - .header("Content-Type", "application/json") - .POST(HttpRequest.BodyPublishers.ofString(new Gson().toJson(reportRequest))) - .build(); - - HttpResponse httpResponse = client.send(httpRequest, HttpResponse.BodyHandlers.ofString()); - this.printResultMessage(issuer, httpResponse); - } catch(IOException | InterruptedException | URISyntaxException e) { - issuer.sendMessage( - Component.text("Internal server description: " + e.getMessage()).color(NamedTextColor.RED) - ); - throw new RuntimeException(e); - } - } - - private void printReports(Player issuer, HttpResponse httpResponse) { - if(httpResponse.statusCode() != 200) { - - Main.logger().warning("Failed to request Reports: " + httpResponse.statusCode()); - issuer.sendMessage( - Component.text() - .append(Component.text("Interner Serverfehler beim abfragen der Reports.", NamedTextColor.RED)) - .appendNewline() - .append(Component.text("Bitte melde dich bei einem Admin!", NamedTextColor.RED)) - ); - return; - } - - List reports = new Gson().fromJson(httpResponse.body(), ReportsResponse.class).from_self; - reports.removeIf(reportInfo -> reportInfo.draft); - if(reports.isEmpty()) { - issuer.sendMessage( - Component.text() - .append(Component.text("Du hast noch niemanden reportet.", NamedTextColor.RED)) - .appendNewline() - .append(Component.text("Um jemanden zu melden, nutze /report", NamedTextColor.GRAY)) - ); - return; - } - - ComponentBuilder component = Component.text(); - - component.append( - Component.newline() - .append(Component.text("Von dir erstellte Reports: ", NamedTextColor.GOLD)) - .appendNewline() + ReportRepository.ReportCreationInfo request = new ReportRepository.ReportCreationInfo( + issuer.getUniqueId(), + offlinePlayer.getUniqueId(), + Optional.ofNullable(reason).orElse("") ); - - reports.forEach(reportInfo -> { - component.append( - Component.text() - .append(Component.text(" - ", NamedTextColor.WHITE)) - .append(Component.text(reportInfo.reported.username, NamedTextColor.WHITE)) - .append(Component.text(String.format(": %s", reportInfo.subject), NamedTextColor.GRAY)) - .clickEvent(ClickEvent.openUrl(reportInfo.url)) - .hoverEvent(HoverEvent.showText(Component.text("Klicke, um den Report einzusehen.", NamedTextColor.GOLD))) - ); - component.appendNewline(); - }); - - issuer.sendMessage(component.build()); + this.createReport(issuer, request); } - private void printResultMessage(Player issuer, HttpResponse httpResponse) { - switch(httpResponse.statusCode()) { + private void createReport(Player issuer, ReportRepository.ReportCreationInfo reportRequest) { + ReqResp createdReport = this.queryRepository(ReportRepository.class) + .createReport(reportRequest); + + switch(createdReport.status()) { case 201: - ReportResponse createdReport = new Gson().fromJson(httpResponse.body(), ReportResponse.class); issuer.sendMessage( Component.text() .append(Component.text("\\/".repeat(20), NamedTextColor.DARK_GRAY)) .appendNewline() - .appendNewline() - .append(Component.text("!!! Report hier fertigstellen !!!", NamedTextColor.GOLD)) + .append(Component.text("⚠ Der Report muss über den folgenden Link fertiggestellt werden!", NamedTextColor.GOLD)) .appendNewline() .appendNewline() .append( Component - .text(" > Hier klicken < ", NamedTextColor.GREEN) - .hoverEvent(HoverEvent.showText(Component.text(createdReport.url).color(NamedTextColor.GREEN))) - .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, createdReport.url)) + .text(createdReport.data().url(), NamedTextColor.GRAY) // URL mit Weltkugel-Emoji + .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, createdReport.data().url())) ) .appendNewline() .appendNewline() - .append( - Component - .text(createdReport.url, NamedTextColor.GRAY) - .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, createdReport.url)) - ) - .appendNewline() + .append(Component.text("Ohne das Fertigstellen des Reports wird dieser nicht bearbeitet!", NamedTextColor.DARK_RED)) .appendNewline() .append(Component.text("/\\".repeat(20), NamedTextColor.DARK_GRAY)) ); @@ -213,7 +94,7 @@ public class Report extends Appliance { case 401: default: - Main.logger().warning("Failed to request Report: " + httpResponse.statusCode()); + Main.logger().warning("Failed to request Report: " + createdReport.status()); issuer.sendMessage( Component.text() .append(Component.text("Interner Serverfehler beim anlegen des Reports.", NamedTextColor.RED)) @@ -224,6 +105,61 @@ public class Report extends Appliance { } } + public void queryReports(Player issuer) { + ReqResp userReports = this.queryRepository(ReportRepository.class) + .queryReports(issuer.getUniqueId()); + + if(userReports.status() != 200) { + Main.logger().warning("Failed to request Reports: " + userReports.status()); + issuer.sendMessage( + Component.text() + .append(Component.text("Interner Serverfehler beim abfragen der Reports.", NamedTextColor.RED)) + .appendNewline() + .append(Component.text("Bitte melde dich bei einem Admin!", NamedTextColor.RED)) + ); + return; + } + + List reports = userReports + .data() + .from_self() + .stream() + .filter(report -> !report.draft()) + .toList() + .reversed(); + + if(reports.isEmpty()) { + issuer.sendMessage( + Component.text() + .append(Component.text("Du hast noch niemanden reportet.", NamedTextColor.RED)) + .appendNewline() + .append(Component.text("Um jemanden zu melden, nutze /report", NamedTextColor.GRAY)) + ); + return; + } + + ComponentBuilder component = Component.text() + .append(Component.newline()) + .append(Component.text("Von dir erstellte Reports: ", NamedTextColor.GOLD)) + .appendNewline(); + + reports.forEach(report -> { + component + .append(Component.text(" - ", NamedTextColor.WHITE)) + .append( + report.reported() != null + ? Component.text(report.reported().username(), NamedTextColor.WHITE) + : Component.text("Unbekannt", NamedTextColor.YELLOW) + ) + .append(Component.text(String.format(": %s", report.subject()), NamedTextColor.GRAY)) + .clickEvent(ClickEvent.openUrl(report.url())) + .hoverEvent(HoverEvent.showText(Component.text("Klicke, um den Report einzusehen.", NamedTextColor.GOLD))); + component.appendNewline(); + }); + + issuer.sendMessage(component.build()); + } + @Override @NotNull protected List> commands() { diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/report/ReportsCommand.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/report/ReportsCommand.java index 6000b83..88d5dea 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/report/ReportsCommand.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/report/ReportsCommand.java @@ -14,6 +14,6 @@ public class ReportsCommand extends ApplianceCommand.PlayerChecked { @Override protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { sender.sendMessage(ComponentUtil.pleaseWait()); - getAppliance().requestReports(getPlayer()); + getAppliance().queryReports(getPlayer()); } }