added feedback

This commit is contained in:
Elias Müller 2024-12-03 20:37:14 +01:00
parent 1572096020
commit eae979ee65
7 changed files with 134 additions and 28 deletions

View File

@ -1,34 +1,99 @@
package eu.mhsl.craftattack.spawn.appliances.feedback; package eu.mhsl.craftattack.spawn.appliances.feedback;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.appliance.Appliance; import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.feedback.commands.FeedbackCommand;
import eu.mhsl.craftattack.spawn.appliances.feedback.commands.RequestFeedbackCommand;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentBuilder;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List; import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.*;
public class Feedback extends Appliance { public class Feedback extends Appliance {
public void requestFeedback(String eventName) { private final URI apiEndpoint;
List<Player> players = Bukkit.getOnlinePlayers().stream()
.map(player -> (Player) player)
.toList();
requestFeedback(eventName, players); public Feedback() {
super("feedback");
this.apiEndpoint = URI.create(Objects.requireNonNull(localConfig().getString("api")));
} }
public void requestFeedback(String eventName, List<Player> receivers) { public void requestFeedback(String eventName, List<Player> receivers, @Nullable String question) {
receivers.forEach(player -> player.sendMessage( Map<UUID, String> feedbackUrls = createPersonalizedUrls(
Component.text() new Request(eventName, receivers.stream().map(Entity::getUniqueId).toList())
.append(Component.text("------------------------------", NamedTextColor.GRAY)) );
System.out.println(feedbackUrls.toString());
Component border = Component.text("-".repeat(40), NamedTextColor.GRAY);
receivers.forEach(player -> {
String feedbackUrl = feedbackUrls.get(player.getUniqueId());
if(feedbackUrl == null) {
Main.logger().warning(String.format("FeedbackUrl not found for player '%s' from backend!", player.getUniqueId()));
return;
}
ComponentBuilder<TextComponent, TextComponent.Builder> message = Component.text()
.append(border)
.appendNewline();
if(question != null) {
message
.append(Component.text(question, NamedTextColor.GREEN))
.appendNewline()
.appendNewline();
}
message
.append(Component.text("Klicke hier und gib uns Feedback, damit wir dein Spielerlebnis verbessern können!", NamedTextColor.DARK_GREEN)
.clickEvent(ClickEvent.openUrl(feedbackUrl)))
.hoverEvent(HoverEvent.showText(Component.text("Klicke, um Feedback zu geben.")))
.appendNewline() .appendNewline()
.append(Component.text("Klicke hier und gib Feedback, damit wir dein Spielerlebnis verbessern können!", NamedTextColor.GREEN) .append(border);
.clickEvent(ClickEvent.openUrl(String.format("https://www.google.com/search?q=%s", eventName))))
.hoverEvent(HoverEvent.showText(Component.text("Klicke, um Feedback zu geben.").color(NamedTextColor.GOLD))) player.sendMessage(message.build());
.appendNewline() });
.append(Component.text("------------------------------", NamedTextColor.GRAY)) }
));
private record Request(String event, List<UUID> users) {}
private final Type responseType = new TypeToken<Map<UUID, String>>(){}.getType();
private Map<UUID, String> createPersonalizedUrls(Request data) {
try(HttpClient client = HttpClient.newHttpClient()) {
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(this.apiEndpoint)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(new Gson().toJson(data)))
.build();
HttpResponse<String> httpResponse = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
return new Gson().fromJson(httpResponse.body(), responseType);
} catch(IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
protected @NotNull List<ApplianceCommand<?>> commands() {
return List.of(
new FeedbackCommand(),
new RequestFeedbackCommand()
);
} }
} }

View File

@ -0,0 +1,22 @@
package eu.mhsl.craftattack.spawn.appliances.feedback.commands;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.feedback.Feedback;
import eu.mhsl.craftattack.spawn.util.text.ComponentUtil;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class FeedbackCommand extends ApplianceCommand.PlayerChecked<Feedback> {
public FeedbackCommand() {
super("feedback");
}
@Override
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception {
sender.sendMessage(ComponentUtil.pleaseWait());
getAppliance().requestFeedback("self-issued-ingame", List.of(getPlayer()), null);
}
}

View File

@ -0,0 +1,21 @@
package eu.mhsl.craftattack.spawn.appliances.feedback.commands;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.feedback.Feedback;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
public class RequestFeedbackCommand extends ApplianceCommand<Feedback> {
public RequestFeedbackCommand() {
super("requestFeedback");
}
@Override
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception {
getAppliance().requestFeedback("admin-issued-ingame", new ArrayList<>(Bukkit.getOnlinePlayers()), String.join(" ", args));
}
}

View File

@ -78,7 +78,7 @@ public class Report extends Appliance {
this.printResultMessage(issuer, httpResponse); this.printResultMessage(issuer, httpResponse);
} catch(IOException | InterruptedException e) { } catch(IOException | InterruptedException e) {
issuer.sendMessage( issuer.sendMessage(
Component.text("Internal server description: " + e.getMessage()).color(NamedTextColor.RED) Component.text("Internal server error: " + e.getMessage()).color(NamedTextColor.RED)
); );
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View File

@ -1,8 +1,7 @@
package eu.mhsl.craftattack.spawn.appliances.report; package eu.mhsl.craftattack.spawn.appliances.report;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import net.kyori.adventure.text.Component; import eu.mhsl.craftattack.spawn.util.text.ComponentUtil;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command; import org.bukkit.command.Command;
@ -24,13 +23,7 @@ public class ReportCommand extends ApplianceCommand.PlayerChecked<Report> {
@Override @Override
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
sender.sendMessage( sender.sendMessage(ComponentUtil.pleaseWait());
Component.newline()
.append(Component.text("Reportanfrage wird erstellt...", NamedTextColor.GREEN))
.appendNewline()
.append(Component.text("Bitte warte einen Augenblick", NamedTextColor.GRAY))
.appendNewline()
);
if(args.length == 0) { if(args.length == 0) {
getAppliance().reportToUnknown(getPlayer()); getAppliance().reportToUnknown(getPlayer());

View File

@ -69,4 +69,7 @@ packselect:
icon: "" # base64 player-head texture, can be obtained from sites like https://minecraft-heads.com/ under developers > Value icon: "" # base64 player-head texture, can be obtained from sites like https://minecraft-heads.com/ under developers > Value
endPrevent: endPrevent:
endDisabled: true endDisabled: true
feedback:
api: https://mhsl.eu/craftattack/api/feedback

View File

@ -48,3 +48,5 @@ commands:
acInform: acInform:
infobar: infobar:
endPrevent: endPrevent:
feedback:
requestFeedback: