A comment that reads "MUST stay in lockstep with TryGetActiveCrossfade (K8)" helps nobody outside the plan that used to have a K8 in it, and the plans are not in this repo. Same for "Spec FR-4", "plan §B.2", "Sub-Task 4.4" and the F/R/M/A/S round codes scattered through the style engine and the self-tests. Personal names go too. "tester feedback from Jin (v1.4.7)" and "Flo decision 2026-06-15" carry the reason fine without naming anyone -- the version and the reason are the parts a reader can act on, and a public repo should not need a cast list to be read. The rule applied throughout: keep the why, drop the reference. Version numbers stay, since those resolve through the changelog. 77 files. ChunkUtil also carried 281 lines of commented-out code -- an older ToChunks variant and two helpers with no callers, inherited and never removed. Deleted; git remembers them.
143 lines
5.2 KiB
C#
143 lines
5.2 KiB
C#
using HellionChat.Code;
|
|
|
|
namespace HellionChat.Privacy;
|
|
|
|
internal static class PrivacyDefaults
|
|
{
|
|
// Failsafe for ChatTypes added by future FFXIV patches. New installs
|
|
// persist unknown channels so a major patch's added ChatType isn't silently
|
|
// dropped before the user can opt in or out. Existing configs keep their
|
|
// explicit choice — see Configuration.cs PrivacyPersistUnknownChannels.
|
|
internal const bool DefaultPersistUnknownChannels = true;
|
|
|
|
// DSGVO Art. 25 (Privacy by Default): only the player's own conversations
|
|
// are persisted out-of-the-box. Public chat, NPC dialogue, system logs and
|
|
// battle messages require explicit opt-in.
|
|
internal static readonly IReadOnlySet<ChatType> PrivacyFirstWhitelist = new HashSet<ChatType>
|
|
{
|
|
ChatType.TellIncoming,
|
|
ChatType.TellOutgoing,
|
|
ChatType.Party,
|
|
ChatType.CrossParty,
|
|
ChatType.Alliance,
|
|
ChatType.FreeCompany,
|
|
ChatType.Linkshell1,
|
|
ChatType.Linkshell2,
|
|
ChatType.Linkshell3,
|
|
ChatType.Linkshell4,
|
|
ChatType.Linkshell5,
|
|
ChatType.Linkshell6,
|
|
ChatType.Linkshell7,
|
|
ChatType.Linkshell8,
|
|
ChatType.CrossLinkshell1,
|
|
ChatType.CrossLinkshell2,
|
|
ChatType.CrossLinkshell3,
|
|
ChatType.CrossLinkshell4,
|
|
ChatType.CrossLinkshell5,
|
|
ChatType.CrossLinkshell6,
|
|
ChatType.CrossLinkshell7,
|
|
ChatType.CrossLinkshell8,
|
|
ChatType.ExtraChatLinkshell1,
|
|
ChatType.ExtraChatLinkshell2,
|
|
ChatType.ExtraChatLinkshell3,
|
|
ChatType.ExtraChatLinkshell4,
|
|
ChatType.ExtraChatLinkshell5,
|
|
ChatType.ExtraChatLinkshell6,
|
|
ChatType.ExtraChatLinkshell7,
|
|
ChatType.ExtraChatLinkshell8,
|
|
};
|
|
|
|
// Per-channel retention in days. Unlisted channels fall back to
|
|
// Configuration.RetentionDefaultDays. Tells: 365, everything else: 90.
|
|
internal static readonly IReadOnlyDictionary<ChatType, int> DefaultRetentionDays =
|
|
new Dictionary<ChatType, int>
|
|
{
|
|
[ChatType.TellIncoming] = 365,
|
|
[ChatType.TellOutgoing] = 365,
|
|
|
|
[ChatType.Party] = 90,
|
|
[ChatType.CrossParty] = 90,
|
|
[ChatType.Alliance] = 90,
|
|
[ChatType.PvpTeam] = 90,
|
|
[ChatType.FreeCompany] = 90,
|
|
|
|
[ChatType.Linkshell1] = 90,
|
|
[ChatType.Linkshell2] = 90,
|
|
[ChatType.Linkshell3] = 90,
|
|
[ChatType.Linkshell4] = 90,
|
|
[ChatType.Linkshell5] = 90,
|
|
[ChatType.Linkshell6] = 90,
|
|
[ChatType.Linkshell7] = 90,
|
|
[ChatType.Linkshell8] = 90,
|
|
|
|
[ChatType.CrossLinkshell1] = 90,
|
|
[ChatType.CrossLinkshell2] = 90,
|
|
[ChatType.CrossLinkshell3] = 90,
|
|
[ChatType.CrossLinkshell4] = 90,
|
|
[ChatType.CrossLinkshell5] = 90,
|
|
[ChatType.CrossLinkshell6] = 90,
|
|
[ChatType.CrossLinkshell7] = 90,
|
|
[ChatType.CrossLinkshell8] = 90,
|
|
|
|
[ChatType.ExtraChatLinkshell1] = 90,
|
|
[ChatType.ExtraChatLinkshell2] = 90,
|
|
[ChatType.ExtraChatLinkshell3] = 90,
|
|
[ChatType.ExtraChatLinkshell4] = 90,
|
|
[ChatType.ExtraChatLinkshell5] = 90,
|
|
[ChatType.ExtraChatLinkshell6] = 90,
|
|
[ChatType.ExtraChatLinkshell7] = 90,
|
|
[ChatType.ExtraChatLinkshell8] = 90,
|
|
};
|
|
|
|
// Casual: Privacy-First + public chat (Say/Shout/Yell, emotes, Novice
|
|
// Network) with a 1-day window so recent RP/trade is searchable but
|
|
// third-party data doesn't accumulate.
|
|
internal static readonly IReadOnlySet<ChatType> CasualWhitelist = new HashSet<ChatType>(
|
|
PrivacyFirstWhitelist
|
|
)
|
|
{
|
|
ChatType.Say,
|
|
ChatType.Shout,
|
|
ChatType.Yell,
|
|
ChatType.CustomEmote,
|
|
ChatType.StandardEmote,
|
|
ChatType.NoviceNetwork,
|
|
};
|
|
|
|
internal static readonly IReadOnlyDictionary<ChatType, int> CasualRetentionOverrides =
|
|
new Dictionary<ChatType, int>
|
|
{
|
|
[ChatType.Say] = 1,
|
|
[ChatType.Shout] = 1,
|
|
[ChatType.Yell] = 1,
|
|
[ChatType.CustomEmote] = 1,
|
|
[ChatType.StandardEmote] = 1,
|
|
[ChatType.NoviceNetwork] = 1,
|
|
};
|
|
|
|
// Roleplay: Privacy-First + Say + both emote types. Public-distance
|
|
// channels (Shout, Yell) stay out — they are public-noise from
|
|
// strangers, not story content. Novice Network also stays out;
|
|
// it is not RP-adjacent and would dilute the profile's intent.
|
|
internal static readonly IReadOnlySet<ChatType> RoleplayWhitelist = new HashSet<ChatType>(
|
|
PrivacyFirstWhitelist
|
|
)
|
|
{
|
|
ChatType.Say,
|
|
ChatType.CustomEmote,
|
|
ChatType.StandardEmote,
|
|
};
|
|
|
|
// RP sessions function as story logs: Say + emotes need a longer
|
|
// window than Casual's 1-day public-chat window. 30 days for Say
|
|
// keeps in-character dialogue scrollable across multiple sessions,
|
|
// 90 days for emotes mirrors the Privacy-First conversation default.
|
|
internal static readonly IReadOnlyDictionary<ChatType, int> RoleplayRetentionOverrides =
|
|
new Dictionary<ChatType, int>
|
|
{
|
|
[ChatType.Say] = 30,
|
|
[ChatType.CustomEmote] = 90,
|
|
[ChatType.StandardEmote] = 90,
|
|
};
|
|
}
|