LoReport/.kiro/specs/lorep-report-plugin/design.md
2025-12-19 12:07:40 +01:00

319 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Design Document: lorep Report Plugin
## Overview
Плагин lorep — система репортов для Paper 1.21, написанная на Java 21. Использует Gradle для сборки, SQLite для хранения данных и интегрируется с Discord через webhooks.
**Технологический стек:**
- Java 21
- Paper API 1.21
- Gradle (Kotlin DSL)
- SQLite (встроенная БД) или PostgreSQL (внешняя БД)
- HikariCP (connection pool для PostgreSQL)
- OkHttp (HTTP клиент для webhooks)
**Git репозиторий:** https://git.lokili.xyz/loki/lorep.git
## Architecture
```mermaid
graph TB
subgraph Plugin
Main[LorepPlugin]
CMD[CommandManager]
GUI[GuiManager]
DB[DatabaseManager]
WH[WebhookService]
CFG[ConfigManager]
end
subgraph External
Discord[Discord Webhook]
SQLite[(SQLite DB)]
end
Main --> CMD
Main --> GUI
Main --> DB
Main --> WH
Main --> CFG
CMD --> DB
CMD --> WH
GUI --> DB
WH --> Discord
DB --> SQLite
CFG --> Main
```
### Структура проекта
```
lorep/
├── .gitignore
├── build.gradle.kts
├── settings.gradle.kts
├── src/
│ └── main/
│ ├── java/
│ │ └── dev/
│ │ └── loki/
│ │ └── lorep/
│ │ ├── LorepPlugin.java
│ │ ├── command/
│ │ │ ├── ReportCommand.java
│ │ │ ├── ReportGuiCommand.java
│ │ │ └── ReportStatsCommand.java
│ │ ├── database/
│ │ │ ├── DatabaseManager.java
│ │ │ ├── SQLiteDatabaseManager.java
│ │ │ ├── PostgreSQLDatabaseManager.java
│ │ │ └── Report.java
│ │ ├── gui/
│ │ │ ├── ReportGui.java
│ │ │ └── GuiClickListener.java
│ │ ├── webhook/
│ │ │ └── DiscordWebhook.java
│ │ ├── config/
│ │ │ └── ConfigManager.java
│ │ └── util/
│ │ ├── TimeUtil.java
│ │ └── MessageUtil.java
│ └── resources/
│ ├── plugin.yml
│ └── config.yml
└── src/
└── test/
└── java/
└── dev/
└── loki/
└── lorep/
├── database/
│ └── DatabaseManagerTest.java
└── util/
└── TimeUtilTest.java
```
## Components and Interfaces
### 1. LorepPlugin (Main Class)
```java
public final class LorepPlugin extends JavaPlugin {
private DatabaseManager databaseManager;
private ConfigManager configManager;
private DiscordWebhook discordWebhook;
@Override
public void onEnable();
@Override
public void onDisable();
// Getters for managers
}
```
### 2. Report (Data Model)
```java
public record Report(
int id,
UUID reporterUuid,
String reporterName,
UUID targetUuid,
String targetName,
String reason,
Instant createdAt
) {}
```
### 3. DatabaseManager
```java
public interface DatabaseManager {
void initialize();
void close();
void saveReport(Report report);
List<Report> getReportsForTarget(UUID targetUuid);
List<Report> getAllReports();
int getReportCount(UUID targetUuid);
boolean hasReported(UUID reporterUuid, UUID targetUuid);
List<Report> getReportsPaginated(int page, int pageSize);
}
// Реализации:
public class SQLiteDatabaseManager implements DatabaseManager { }
public class PostgreSQLDatabaseManager implements DatabaseManager { }
```
### 4. DiscordWebhook
```java
public class DiscordWebhook {
public DiscordWebhook(String webhookUrl);
public void sendReport(Report report);
}
```
### 5. ConfigManager
```java
public class ConfigManager {
public String getWebhookUrl();
public String getDatabasePath();
public String getMessage(String key);
}
```
### 6. ReportGui
```java
public class ReportGui {
public void open(Player player, int page);
public ItemStack createReportItem(Report report, int totalReports);
}
```
## Data Models
### Report Entity
| Field | Type | Description |
|-------|------|-------------|
| id | INTEGER | Primary key, auto-increment |
| reporter_uuid | TEXT | UUID репортера |
| reporter_name | TEXT | Имя репортера |
| target_uuid | TEXT | UUID цели |
| target_name | TEXT | Имя цели |
| reason | TEXT | Причина репорта |
| created_at | INTEGER | Unix timestamp создания |
### SQL Schema
```sql
CREATE TABLE IF NOT EXISTS reports (
id INTEGER PRIMARY KEY AUTOINCREMENT,
reporter_uuid TEXT NOT NULL,
reporter_name TEXT NOT NULL,
target_uuid TEXT NOT NULL,
target_name TEXT NOT NULL,
reason TEXT NOT NULL,
created_at INTEGER NOT NULL
);
CREATE INDEX idx_target_uuid ON reports(target_uuid);
CREATE INDEX idx_reporter_target ON reports(reporter_uuid, target_uuid);
```
### Configuration (config.yml)
```yaml
# Discord Webhook URL
webhook-url: ""
# Database settings
database:
# Type: sqlite or postgresql
type: "sqlite"
# SQLite settings
sqlite:
file: "reports.db"
# PostgreSQL settings
postgresql:
host: "localhost"
port: 5432
database: "lorep"
username: "lorep"
password: "password"
pool-size: 10
# Messages
messages:
report-sent: "&aРепорт успешно отправлен!"
already-reported: "&cВы уже отправляли репорт на этого игрока!"
self-report: "&cВы не можете отправить репорт на себя!"
player-not-found: "&cИгрок не найден!"
no-permission: "&cУ вас нет прав на эту команду!"
usage: "&eИспользование: /report <ник> <причина>"
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property 1: Report Creation Integrity
*For any* valid reporter UUID, target UUID, and reason string, creating a report and then querying reports for that target SHALL return a list containing the created report with matching fields.
**Validates: Requirements 1.1, 2.1**
### Property 2: Duplicate Report Prevention
*For any* reporter-target pair, if a report already exists from that reporter to that target, attempting to create another report SHALL be rejected.
**Validates: Requirements 1.2**
### Property 3: Report Persistence Round-Trip
*For any* set of reports saved to the database, reloading the database SHALL return the same reports with identical data.
**Validates: Requirements 2.2**
### Property 4: Report Ordering
*For any* collection of reports with different timestamps, querying all reports SHALL return them sorted by creation timestamp in descending order (newest first).
**Validates: Requirements 2.3**
### Property 5: Webhook Payload Completeness
*For any* report sent to the webhook, the payload SHALL contain reporter name, target name, reason, and formatted timestamp.
**Validates: Requirements 3.1**
### Property 6: Pagination Correctness
*For any* list of N reports and page size P, requesting page K SHALL return at most P reports starting from index K*P, and the total page count SHALL equal ceil(N/P).
**Validates: Requirements 4.4**
### Property 7: Report Count Accuracy
*For any* target UUID, the report count returned by getReportCount SHALL equal the actual number of reports in the database for that target.
**Validates: Requirements 5.1**
### Property 8: Permission Enforcement
*For any* command execution, if the player lacks the required permission, the command SHALL be denied and return false.
**Validates: Requirements 6.1, 6.2, 6.3**
### Property 9: Configuration Parsing
*For any* valid config.yml file, parsing SHALL correctly extract webhook URL and database path values.
**Validates: Requirements 7.1, 7.3, 7.4**
## Error Handling
| Scenario | Handling |
|----------|----------|
| Database connection failure | Log error, disable plugin gracefully |
| Webhook request failure | Log warning, continue operation |
| Invalid player name | Return error message to player |
| Missing config values | Use default values |
| SQL exceptions | Log error, return empty result |
## Testing Strategy
### Property-Based Testing Library
- **JQwik** — библиотека для property-based тестирования в Java
- Минимум 100 итераций на каждый property test
### Unit Tests
- DatabaseManager: CRUD операции, pagination
- TimeUtil: форматирование времени
- ConfigManager: парсинг конфигурации
### Property-Based Tests
Каждый property test должен быть аннотирован:
```java
// **Feature: lorep-report-plugin, Property 1: Report Creation Integrity**
@Property(tries = 100)
void reportCreationIntegrity(@ForAll UUID reporter, @ForAll UUID target, @ForAll String reason) {
// test implementation
}
```
### Integration Tests
- Полный цикл создания репорта
- GUI открытие и навигация
- Webhook отправка (с mock сервером)