Delete _trash/2026-05-07T19-39-34-009Z/_trash/2026-05-07T19-39-23-130Z/src/main/java/net/viper/status/modules/chat/ReportManager.java via Git Manager GUI
This commit is contained in:
@@ -1,227 +0,0 @@
|
||||
package net.viper.status.modules.chat;
|
||||
|
||||
import java.io.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Verwaltet Spieler-Reports (/report).
|
||||
*
|
||||
* Reports werden mit einer eindeutigen ID (z.B. RPT-0001) gespeichert und
|
||||
* bleiben offen, bis ein Admin sie explizit mit /reportclose <ID> schließt.
|
||||
*
|
||||
* Online-Admins werden sofort benachrichtigt.
|
||||
* Offline-Admins erhalten eine verzögerte Benachrichtigung beim nächsten Login
|
||||
* (gesteuert von außen via getPendingNotificationFor()).
|
||||
*
|
||||
* Speicherformat (chat_reports.dat):
|
||||
* id|reporter|reporterUUID|reported|server|messageContext|reason|timestamp|closed|closedBy
|
||||
*/
|
||||
public class ReportManager {
|
||||
|
||||
private final File file;
|
||||
private final Logger logger;
|
||||
|
||||
/** Alle Reports (offen und geschlossen). */
|
||||
private final ConcurrentHashMap<String, ChatReport> reports = new ConcurrentHashMap<>();
|
||||
|
||||
/** Zähler für Report-IDs. Wird beim Laden synchronisiert. */
|
||||
private final AtomicInteger idCounter = new AtomicInteger(0);
|
||||
|
||||
private static final SimpleDateFormat DATE_FMT = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
|
||||
|
||||
// ===== Report-Datenklasse =====
|
||||
|
||||
public static class ChatReport {
|
||||
public String id;
|
||||
public String reporterName;
|
||||
public UUID reporterUUID;
|
||||
public String reportedName;
|
||||
public String server;
|
||||
public String messageContext; // letzte bekannte Chatnachricht des Gemeldeten
|
||||
public String reason;
|
||||
public long timestamp;
|
||||
public boolean closed;
|
||||
public String closedBy; // Name des schließenden Admins (oder leer)
|
||||
|
||||
public String getFormattedTime() {
|
||||
return DATE_FMT.format(new Date(timestamp));
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Konstruktor =====
|
||||
|
||||
public ReportManager(File dataFolder, Logger logger) {
|
||||
this.file = new File(dataFolder, "chat_reports.dat");
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
// ===== Report-Logik =====
|
||||
|
||||
/**
|
||||
* Erstellt einen neuen Report.
|
||||
*
|
||||
* @param reporterName Name des meldenden Spielers
|
||||
* @param reporterUUID UUID des meldenden Spielers
|
||||
* @param reportedName Name des gemeldeten Spielers
|
||||
* @param server Server, auf dem sich der Reporter befand
|
||||
* @param messageContext Letzte bekannte Nachricht des Gemeldeten (für Kontext)
|
||||
* @param reason Freitext-Begründung
|
||||
* @return die neue Report-ID (z.B. RPT-0001)
|
||||
*/
|
||||
public String createReport(String reporterName, UUID reporterUUID,
|
||||
String reportedName, String server,
|
||||
String messageContext, String reason) {
|
||||
String id = String.format("RPT-%04d", idCounter.incrementAndGet());
|
||||
|
||||
ChatReport report = new ChatReport();
|
||||
report.id = id;
|
||||
report.reporterName = reporterName;
|
||||
report.reporterUUID = reporterUUID;
|
||||
report.reportedName = reportedName;
|
||||
report.server = server;
|
||||
report.messageContext = messageContext != null ? messageContext : "";
|
||||
report.reason = reason;
|
||||
report.timestamp = System.currentTimeMillis();
|
||||
report.closed = false;
|
||||
report.closedBy = "";
|
||||
|
||||
reports.put(id, report);
|
||||
save();
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schließt einen Report.
|
||||
*
|
||||
* @param id Report-ID (z.B. RPT-0001, case-insensitiv)
|
||||
* @param adminName Name des Admins, der den Report schließt
|
||||
* @return true wenn erfolgreich geschlossen, false wenn nicht gefunden / bereits geschlossen
|
||||
*/
|
||||
public boolean closeReport(String id, String adminName) {
|
||||
ChatReport report = getReport(id);
|
||||
if (report == null || report.closed) return false;
|
||||
report.closed = true;
|
||||
report.closedBy = adminName;
|
||||
save();
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Gibt einen Report nach ID zurück (case-insensitiv). */
|
||||
public ChatReport getReport(String id) {
|
||||
if (id == null) return null;
|
||||
return reports.get(id.toUpperCase());
|
||||
}
|
||||
|
||||
/** Gibt alle offenen Reports chronologisch (älteste zuerst) zurück. */
|
||||
public List<ChatReport> getOpenReports() {
|
||||
List<ChatReport> list = new ArrayList<>();
|
||||
for (ChatReport r : reports.values()) {
|
||||
if (!r.closed) list.add(r);
|
||||
}
|
||||
list.sort(Comparator.comparingLong(r -> r.timestamp));
|
||||
return list;
|
||||
}
|
||||
|
||||
/** Gibt alle Reports chronologisch zurück (auch geschlossene). */
|
||||
public List<ChatReport> getAllReports() {
|
||||
List<ChatReport> list = new ArrayList<>(reports.values());
|
||||
list.sort(Comparator.comparingLong(r -> r.timestamp));
|
||||
return list;
|
||||
}
|
||||
|
||||
/** Anzahl offener Reports. */
|
||||
public int getOpenCount() {
|
||||
int count = 0;
|
||||
for (ChatReport r : reports.values()) if (!r.closed) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
// ===== Persistenz =====
|
||||
|
||||
public void save() {
|
||||
try (BufferedWriter bw = new BufferedWriter(
|
||||
new OutputStreamWriter(new FileOutputStream(file), "UTF-8"))) {
|
||||
for (ChatReport r : reports.values()) {
|
||||
bw.write(
|
||||
esc(r.id) + "|" +
|
||||
esc(r.reporterName) + "|" +
|
||||
r.reporterUUID + "|" +
|
||||
esc(r.reportedName) + "|" +
|
||||
esc(r.server) + "|" +
|
||||
esc(r.messageContext) + "|" +
|
||||
esc(r.reason) + "|" +
|
||||
r.timestamp + "|" +
|
||||
r.closed + "|" +
|
||||
esc(r.closedBy != null ? r.closedBy : "")
|
||||
);
|
||||
bw.newLine();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.warning("[ChatModule] Fehler beim Speichern der Reports: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void load() {
|
||||
reports.clear();
|
||||
if (!file.exists()) return;
|
||||
|
||||
int maxNum = 0;
|
||||
try (BufferedReader br = new BufferedReader(
|
||||
new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
line = line.trim();
|
||||
if (line.isEmpty()) continue;
|
||||
String[] p = line.split("\\|", -1);
|
||||
if (p.length < 10) continue;
|
||||
try {
|
||||
ChatReport r = new ChatReport();
|
||||
r.id = unesc(p[0]);
|
||||
r.reporterName = unesc(p[1]);
|
||||
r.reporterUUID = UUID.fromString(p[2]);
|
||||
r.reportedName = unesc(p[3]);
|
||||
r.server = unesc(p[4]);
|
||||
r.messageContext = unesc(p[5]);
|
||||
r.reason = unesc(p[6]);
|
||||
r.timestamp = Long.parseLong(p[7]);
|
||||
r.closed = Boolean.parseBoolean(p[8]);
|
||||
r.closedBy = unesc(p[9]);
|
||||
reports.put(r.id.toUpperCase(), r);
|
||||
|
||||
// Zähler auf höchste bekannte Nummer synchronisieren
|
||||
if (r.id.toUpperCase().startsWith("RPT-")) {
|
||||
try {
|
||||
int num = Integer.parseInt(r.id.substring(4));
|
||||
if (num > maxNum) maxNum = num;
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.warning("[ChatModule] Fehler beim Laden der Reports: " + e.getMessage());
|
||||
}
|
||||
idCounter.set(maxNum);
|
||||
|
||||
}
|
||||
|
||||
// ===== Escape-Helfer (Pipe-Zeichen und Zeilenumbrüche escapen) =====
|
||||
|
||||
private static String esc(String s) {
|
||||
if (s == null) return "";
|
||||
return s.replace("\\", "\\\\")
|
||||
.replace("|", "\\p")
|
||||
.replace("\n", "\\n")
|
||||
.replace("\r", "");
|
||||
}
|
||||
|
||||
private static String unesc(String s) {
|
||||
if (s == null) return "";
|
||||
return s.replace("\\n", "\n")
|
||||
.replace("\\p", "|")
|
||||
.replace("\\\\", "\\");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user