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

9.8 KiB
Raw Blame History

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

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)

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)

public record Report(
    int id,
    UUID reporterUuid,
    String reporterName,
    UUID targetUuid,
    String targetName,
    String reason,
    Instant createdAt
) {}

3. DatabaseManager

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

public class DiscordWebhook {
    public DiscordWebhook(String webhookUrl);
    
    public void sendReport(Report report);
}

5. ConfigManager

public class ConfigManager {
    public String getWebhookUrl();
    public String getDatabasePath();
    public String getMessage(String key);
}

6. ReportGui

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

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)

# 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 должен быть аннотирован:

// **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 сервером)