using System; using System.Linq; using System.Text.RegularExpressions; using Dalamud.Plugin.Services; using Lumina.Excel; using Lumina.Text.Payloads; using Lumina.Text.ReadOnly; namespace LLib; public static class DataManagerExtensions { public static ReadOnlySeString? GetSeString(this IDataManager dataManager, string key) where T : struct, IQuestDialogueText, IExcelRow { ArgumentNullException.ThrowIfNull(dataManager, "dataManager"); return dataManager.GetExcelSheet().Cast().SingleOrDefault((T? x) => x.Value.Key == key)?.Value; } public static string? GetString(this IDataManager dataManager, string key, IPluginLog? pluginLog) where T : struct, IQuestDialogueText, IExcelRow { string text = dataManager.GetSeString(key)?.WithCertainMacroCodeReplacements(); pluginLog?.Verbose($"{typeof(T).Name}.{key} => {text}"); return text; } public static Regex? GetRegex(this IDataManager dataManager, string key, IPluginLog? pluginLog) where T : struct, IQuestDialogueText, IExcelRow { ReadOnlySeString? seString = dataManager.GetSeString(key); if (!seString.HasValue) { return null; } string text = string.Join("", seString.Select((ReadOnlySePayload payload) => (payload.Type == ReadOnlySePayloadType.Text) ? Regex.Escape(payload.ToString()) : "(.*)")); pluginLog?.Verbose($"{typeof(T).Name}.{key} => /{text}/"); return new Regex(text); } public static ReadOnlySeString? GetSeString(this IDataManager dataManager, uint rowId, Func mapper) where T : struct, IExcelRow { ArgumentNullException.ThrowIfNull(dataManager, "dataManager"); ArgumentNullException.ThrowIfNull(mapper, "mapper"); T? rowOrDefault = dataManager.GetExcelSheet().GetRowOrDefault(rowId); if (!rowOrDefault.HasValue) { return null; } return mapper(rowOrDefault.Value); } public static string? GetString(this IDataManager dataManager, uint rowId, Func mapper, IPluginLog? pluginLog = null) where T : struct, IExcelRow { string text = dataManager.GetSeString(rowId, mapper)?.WithCertainMacroCodeReplacements(); pluginLog?.Verbose($"{typeof(T).Name}.{rowId} => {text}"); return text; } public static Regex? GetRegex(this IDataManager dataManager, uint rowId, Func mapper, IPluginLog? pluginLog = null) where T : struct, IExcelRow { ReadOnlySeString? seString = dataManager.GetSeString(rowId, mapper); if (!seString.HasValue) { return null; } Regex regex = seString.ToRegex(); pluginLog?.Verbose($"{typeof(T).Name}.{rowId} => /{regex}/"); return regex; } public static Regex? GetRegex(this T excelRow, Func mapper, IPluginLog? pluginLog) where T : struct, IExcelRow { ArgumentNullException.ThrowIfNull(mapper, "mapper"); ReadOnlySeString? text = mapper(excelRow); if (!text.HasValue) { return null; } Regex regex = text.ToRegex(); pluginLog?.Verbose($"{typeof(T).Name}.regex => /{regex}/"); return regex; } public static Regex ToRegex(this ReadOnlySeString? text) { ArgumentNullException.ThrowIfNull(text, "text"); return new Regex(string.Join("", text.Value.Select((ReadOnlySePayload payload) => (payload.Type == ReadOnlySePayloadType.Text) ? Regex.Escape(payload.ToString()) : "(.*)"))); } public static string WithCertainMacroCodeReplacements(this ReadOnlySeString text) { return string.Join("", text.Select((ReadOnlySePayload payload) => payload.Type switch { ReadOnlySePayloadType.Text => payload.ToString(), ReadOnlySePayloadType.Macro => payload.MacroCode switch { MacroCode.NewLine => "", MacroCode.NonBreakingSpace => " ", MacroCode.Hyphen => "-", MacroCode.SoftHyphen => "", _ => payload.ToString(), }, _ => payload.ToString(), })); } }