Commit Graph

22 Commits

Author SHA1 Message Date
JonKazama-Hellion 92bb368d2b feat(auto-tell-tabs): add GetTellHistoryWithSender query and ChunkUtil sender helper 2026-05-02 12:52:58 +02:00
JonKazama-Hellion 4f25c2756b Tighten DbViewer paging — int constant and matching SQL parameter name
Audit findings M-1 and M-2. Two small consistency issues in the
upstream DbViewer paging path that we now own as a fork:

  - RowPerPage is a row count and should be an int. The upstream
    declaration was 1000.0f, which forced an implicit float divide
    in Math.Ceiling and an implicit float-to-integer conversion when
    SQLite bound the LIMIT parameter. Switching the constant to int
    and casting Count to double right at the division keeps the
    ceiling math intact while making the type story honest.

  - GetPagedDateRange's SQL uses the placeholder $OffsetCount, but
    the matching AddWithValue call passed the unprefixed name
    "OffsetCount". Microsoft.Data.Sqlite tolerates this today, so
    paging still worked; another provider or a stricter future
    version would not. Re-aligned the parameter name with the SQL.

No behavioural change for users — paging continues to return 1000
rows per page. The fixes are kept on the fork rather than offered
upstream because the project's recent triage history makes a
non-trivial PR turnaround unlikely.
2026-05-02 02:56:40 +02:00
JonKazama-Hellion 68a6910c53 Add message export for GDPR Art. 15 right of access
The privacy story is incomplete without a way to actually hand the
data over. New Export section in the Privacy tab streams matching
messages to a Markdown, JSON or CSV file using Dalamud's file
dialog and a background thread, so the settings UI stays
responsive even when the export crawls a 150k-message archive.

MessageStore.StreamForExport returns a MessageEnumerator over
non-deleted rows filtered by ChatType list and date range, sorted
ascending. MessageExporter.ExportToFile takes that enumerator,
optionally narrows by SenderSource.TextValue substring (case-
insensitive), and writes one of three formats:

  Markdown — human-readable, day headers, [HH:mm] ChatType Sender:
  prefix per line, trailing total.

  JSON — single object with metadata (filter snapshot, exported_at,
  plugin name) and a messages array carrying id, ISO-8601 date,
  numeric and named ChatType, source/target kinds, receiver,
  content_id, sender plaintext, content plaintext.

  CSV — header line plus quoted-when-needed rows for spreadsheet
  ingestion.

Sender plaintext, channel filter, date range and format are
exposed as form fields above the Export button. Empty channel
selection means "all stored channels", a 0-day range means "no
time limit". Result count and target path are reported via
WrapperUtil notifications.
2026-05-01 20:41:58 +02:00
JonKazama-Hellion 68c7185cea Add per-channel message retention with daily background sweep
Privacy filter trimmed history "by what" — this adds the time axis.
Each ChatType gets its own retention window in days; channels
without an explicit override fall back to a configurable global
default. The master switch defaults to OFF: the plugin never
deletes history without explicit user consent.

MessageStore.DeleteByRetentionPolicy builds an OR'd WHERE clause
over (ChatType = X AND Date < cutoff_X) plus a NOT IN catch-all
for the global default, hard-deletes matches, and only runs VACUUM
when something was actually removed.

Plugin.RunRetentionSweepIfDue runs at most once per 24 hours on a
background thread (off the load path) and persists the timestamp
so subsequent restarts skip the sweep until enough time has
passed. The Privacy tab gains a retention section with the master
switch, default-days input, per-channel override tree, reset
buttons, and a Ctrl+Shift "apply now" action that mirrors the
auto-sweep but on demand.

Spec defaults: Tells 365 days, own-conversation channels (Party,
Cross-Party, Alliance, PvP Team, FC, Linkshells 1-8, Cross-World
Linkshells 1-8, ExtraChat 1-8) 90 days, fallback 30 days.
2026-05-01 18:47:31 +02:00
JonKazama-Hellion 2401ea5864 Add retroactive cleanup for the existing database
The privacy filter only catches new messages. Two new MessageStore
methods support a one-shot retroactive sweep: GetMessageCountsByChatType
returns a (ChatType, count) snapshot so the UI can preview the impact,
and CleanupRetainOnly hard-deletes everything outside the supplied
allowlist and runs VACUUM to reclaim disk space.

The Privacy tab gains a new section with a refresh-preview button, a
keep/delete summary, a per-channel breakdown tree, and a Ctrl+Shift
confirm. The cleanup runs on a background thread so a 800+ MB VACUUM
does not block the settings UI; tabs are rebuilt via the framework
thread once the delete finishes. The cleanup deliberately uses the
saved Plugin.Config whitelist (not unsaved Mutable edits) so it stays
consistent with the prospective filter.
2026-05-01 18:34:28 +02:00
JonKazama-Hellion 1ad5cb3164 Add privacy filter with channel whitelist (GDPR Art. 25)
Introduce an opt-out channel whitelist so the database only persists
messages from channels the user explicitly wants to keep. Default
profile follows GDPR data minimization: own conversations only
(Tells, Party, FC, Linkshells, Cross-World Linkshells, Alliance,
ExtraChat). Public chat (Say/Shout/Yell), Novice Network, NPC
dialogue and system logs are dropped by default.

The filter sits inside MessageStore.UpsertMessage so any current or
future write path is covered uniformly. Configuration provides an
IsAllowedForStorage(ChatType) helper plus a "persist unknown
channels" failsafe (default off) for ChatTypes added by future
patches.

A new Privacy settings tab exposes the whitelist as grouped
checkboxes with three preset buttons (Privacy-First, Clear all,
Select all). Configuration version bumps from 6 to 7; existing
users are migrated to the Privacy-First defaults on first load
and notified once via the Dalamud notification manager.

Also includes a small .env.example and gitignore hygiene for local
development setup.
2026-05-01 18:20:09 +02:00
JonKazama-Hellion 94064bf9e4 Make Migrate3 idempotent against partial application
If Migrate3 has already applied its schema changes but failed to
bump user_version (e.g. process crashed between ALTER and
SetMigrationVersion), the next run currently hits a duplicate
column error because ALTER TABLE ADD COLUMN is not idempotent in
SQLite.

Detect the recovery case by checking for the presence of the v3
target columns and the absence of the dropped Code column, and
just record the migration version when found.
2026-05-01 18:19:39 +02:00
Infi 7dc34c6013 - Sort rows in the database by date
- Add fast buttons to add/remove all channels
2026-05-01 02:10:10 +02:00
Infi 33c922aaf7 - Potential fix for null ref error
- Add logging around migration
2026-04-30 22:27:23 +02:00
Infi dcf77e27f2 - Fix migration not running for new users
- Use PlayerState for character
2026-04-30 18:14:15 +02:00
Infi b4cb8b25ec - API 15
- Migrate config for API 15
- Migrate database for API 15
- Allow usage of new target source
- Implement first tell target option
2026-04-30 02:59:58 +02:00
Infi df0773ac65 - Implement message history export to text file 2026-04-10 22:17:37 +02:00
Infi 592f069f17 - Small cleanup 2025-06-22 20:17:58 +02:00
Darnell Williams 2cfd1b1487 Improve resource disposal practices
Wraps enumerators and commands in proper using blocks to ensure cleanup.
Adds async disposal for enumerators, reducing resource leakage risks.
2025-05-29 15:04:17 -05:00
Infi 5a78877abf - Increase page count
- /chat2Viewer is now sorted by date
- Echo everything that hasn't any channel set
- Fixed channel inputs are now enforced
- Added a warning for ECL channel mismatch
2025-02-03 13:05:26 +01:00
Infi 3cfe65d2d4 - More ImRaii
- Cleanup
- Spanish, French, Dutch, Chinese loc update
2024-11-21 11:58:22 +01:00
Infi 88fbb24ff0 - Migrate DB to v2 (Channel)
- Add channel selection to DBViewer
2024-05-22 19:25:36 +02:00
Infi c2131eb07b Implement DBViewer 2024-05-22 14:53:30 +02:00
Dean Sheather 0004bcb561 fix: avoid loading failed parse messages again 2024-05-14 11:23:04 +10:00
Infi 4210d634ab BTTV emote support part 1 & keep Input focus option 2024-05-08 00:04:07 +02:00
Infi ed5cedefd2 remove message limit text as it doesn't exist for database itself 2024-04-21 01:59:04 +02:00
Dean Sheather bb6c6b0034 feat: replace LiteDB with Sqlite
- Replace LiteDB database engine with Sqlite
  Note: old databases will not be deleted
- Message duplication detection improvements
- Tolerate parse errors in release builds, log them
2024-04-20 21:18:51 +10:00