feat: make reporting better
This commit is contained in:
parent
02f020c399
commit
5a1990d30c
|
@ -39,6 +39,6 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="DalamudPackager" Version="1.2.1" />
|
||||
<PackageReference Include="Fody" Version="6.5.1" PrivateAssets="all" />
|
||||
<PackageReference Include="ResourcesMerge.Fody" Version="1.0.1" PrivateAssets="all" />
|
||||
<PackageReference Include="ResourcesMerge.Fody" Version="1.0.3" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ConsoleTables" Version="2.4.2"/>
|
||||
<PackageReference Include="CsvHelper" Version="27.0.1"/>
|
||||
<PackageReference Include="CsvHelper" Version="27.0.2"/>
|
||||
<PackageReference Include="Microsoft.ML" Version="1.5.5"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -50,21 +50,7 @@ namespace NoSoliciting {
|
|||
return;
|
||||
}
|
||||
|
||||
Task.Run(async () => {
|
||||
var status = await this.Plugin.Ui.Report.ReportMessageAsync(message);
|
||||
switch (status) {
|
||||
case ReportStatus.Successful: {
|
||||
var msg = Language.ReportToastSuccess;
|
||||
this.Plugin.Interface.Framework.Gui.Toast.ShowNormal(string.Format(msg, listing.Name));
|
||||
break;
|
||||
}
|
||||
case ReportStatus.Failure: {
|
||||
var msg = Language.ReportToastFailure;
|
||||
this.Plugin.Interface.Framework.Gui.Toast.ShowError(string.Format(msg, listing.Name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
this.Plugin.Ui.Report.ToShowModal = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,23 +84,20 @@ namespace NoSoliciting {
|
|||
this.LastBatch = args.BatchNumber;
|
||||
|
||||
var version = this.Plugin.MlFilter?.Version;
|
||||
var reason = this.MlListingFilterReason(listing);
|
||||
|
||||
if (version == null) {
|
||||
return;
|
||||
}
|
||||
var (category, reason) = this.MlListingFilterReason(listing);
|
||||
|
||||
this.Plugin.AddPartyFinderHistory(new Message(
|
||||
version.Value,
|
||||
version,
|
||||
ChatType.None,
|
||||
listing.ContentIdLower,
|
||||
listing.Name,
|
||||
listing.Description,
|
||||
true,
|
||||
reason
|
||||
category,
|
||||
reason == "custom",
|
||||
reason == "ilvl"
|
||||
));
|
||||
|
||||
if (reason == null) {
|
||||
if (category == null && reason == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -123,10 +120,6 @@ namespace NoSoliciting {
|
|||
}
|
||||
|
||||
private bool MlFilterMessage(XivChatType type, uint senderId, SeString sender, SeString message) {
|
||||
if (this.Plugin.MlFilter == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var chatType = ChatTypeExt.FromDalamud(type);
|
||||
|
||||
// NOTE: don't filter on user-controlled chat types here because custom filters are supposed to check all
|
||||
|
@ -137,80 +130,81 @@ namespace NoSoliciting {
|
|||
|
||||
var text = message.TextValue;
|
||||
|
||||
string? reason = null;
|
||||
var custom = false;
|
||||
MessageCategory? classification = null;
|
||||
|
||||
// step 1. check for custom filters if enabled
|
||||
var filter = this.Plugin.Config.CustomChatFilter
|
||||
&& Chat.MatchesCustomFilters(text, this.Plugin.Config)
|
||||
&& SetReason(out reason, "custom");
|
||||
var filter = false;
|
||||
if (this.Plugin.Config.CustomChatFilter && Chat.MatchesCustomFilters(text, this.Plugin.Config)) {
|
||||
filter = true;
|
||||
custom = true;
|
||||
}
|
||||
|
||||
// only look at ml if message >= min words
|
||||
if (!filter && text.Trim().Split(' ').Length >= MinWords) {
|
||||
if (!filter && this.Plugin.MlFilter != null && text.Trim().Split(' ').Length >= MinWords) {
|
||||
// step 2. classify the message using the model
|
||||
var category = this.Plugin.MlFilter.ClassifyMessage((ushort) chatType, text);
|
||||
|
||||
// step 2a. only filter if configured to act on this channel
|
||||
filter = category != MessageCategory.Normal
|
||||
&& this.Plugin.Config.MlEnabledOn(category, chatType)
|
||||
&& SetReason(out reason, category.Name());
|
||||
if (category != MessageCategory.Normal && this.Plugin.Config.MlEnabledOn(category, chatType)) {
|
||||
filter = true;
|
||||
classification = category;
|
||||
}
|
||||
}
|
||||
|
||||
this.Plugin.AddMessageHistory(new Message(
|
||||
this.Plugin.MlFilter.Version,
|
||||
var history = new Message(
|
||||
this.Plugin.MlFilter?.Version,
|
||||
ChatTypeExt.FromDalamud(type),
|
||||
senderId,
|
||||
sender,
|
||||
message,
|
||||
true,
|
||||
reason
|
||||
));
|
||||
classification,
|
||||
custom,
|
||||
false
|
||||
);
|
||||
this.Plugin.AddMessageHistory(history);
|
||||
|
||||
if (filter && this.Plugin.Config.LogFilteredChat) {
|
||||
PluginLog.Log($"Filtered chat message ({reason}): {text}");
|
||||
PluginLog.Log($"Filtered chat message ({history.FilterReason ?? "unknown"}): {text}");
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
private string? MlListingFilterReason(PartyFinderListing listing) {
|
||||
private (MessageCategory?, string?) MlListingFilterReason(PartyFinderListing listing) {
|
||||
if (this.Plugin.MlFilter == null) {
|
||||
return null;
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
// ignore private listings if configured
|
||||
if (!this.Plugin.Config.ConsiderPrivatePfs && listing[SearchAreaFlags.Private]) {
|
||||
return null;
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
var desc = listing.Description.TextValue;
|
||||
|
||||
// step 1. check if pf has an item level that's too high
|
||||
if (this.Plugin.Config.FilterHugeItemLevelPFs && listing.MinimumItemLevel > FilterUtil.MaxItemLevelAttainable(this.Plugin.Interface.Data)) {
|
||||
return "ilvl";
|
||||
return (null, "ilvl");
|
||||
}
|
||||
|
||||
// step 2. check custom filters
|
||||
if (this.Plugin.Config.CustomPFFilter && PartyFinder.MatchesCustomFilters(desc, this.Plugin.Config)) {
|
||||
return "custom";
|
||||
return (null, "custom");
|
||||
}
|
||||
|
||||
// only look at ml for pfs >= min words
|
||||
if (desc.Trim().Spacify().Split(' ').Length < MinWords) {
|
||||
return null;
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
var category = this.Plugin.MlFilter.ClassifyMessage((ushort) ChatType.None, desc);
|
||||
|
||||
if (category != MessageCategory.Normal && this.Plugin.Config.MlEnabledOn(category, ChatType.None)) {
|
||||
return category.Name();
|
||||
return (category, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool SetReason(out string reason, string value) {
|
||||
reason = value;
|
||||
return true;
|
||||
return (null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ using System.Globalization;
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Dalamud.Plugin;
|
||||
using ImGuiNET;
|
||||
using NoSoliciting.Ml;
|
||||
using NoSoliciting.Resources;
|
||||
|
||||
namespace NoSoliciting.Interface {
|
||||
|
@ -34,6 +34,8 @@ namespace NoSoliciting.Interface {
|
|||
set => this._showReporting = value;
|
||||
}
|
||||
|
||||
internal Message? ToShowModal { get; set; }
|
||||
|
||||
public Report(Plugin plugin) {
|
||||
this.Plugin = plugin;
|
||||
}
|
||||
|
@ -47,6 +49,13 @@ namespace NoSoliciting.Interface {
|
|||
}
|
||||
|
||||
public void Draw() {
|
||||
var toShow = this.ToShowModal;
|
||||
if (toShow != null) {
|
||||
if (!this.SetUpReportModal(toShow)) {
|
||||
ImGui.OpenPopup($"###modal-message-{toShow.Id}");
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.ShowReporting) {
|
||||
return;
|
||||
}
|
||||
|
@ -102,7 +111,7 @@ namespace NoSoliciting.Interface {
|
|||
foreach (var message in this.Plugin.MessageHistory) {
|
||||
ImGui.TableNextRow();
|
||||
|
||||
if (message.FilterReason != null) {
|
||||
if (message.Filtered) {
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(238f / 255f, 71f / 255f, 71f / 255f, 1f));
|
||||
}
|
||||
|
||||
|
@ -112,11 +121,11 @@ namespace NoSoliciting.Interface {
|
|||
.Select(payload => payload.Text)
|
||||
.FirstOrDefault() ?? "";
|
||||
|
||||
if (AddRow(message.Timestamp.ToString(CultureInfo.CurrentCulture), message.ChatType.Name(this.Plugin.Interface.Data), message.FilterReason ?? "", sender, message.Content.TextValue)) {
|
||||
if (AddRow(message.Timestamp.ToString(CultureInfo.CurrentCulture), message.ChatType.Name(this.Plugin.Interface.Data), message.FilterReason ?? string.Empty, sender, message.Content.TextValue)) {
|
||||
ImGui.OpenPopup($"###modal-message-{message.Id}");
|
||||
}
|
||||
|
||||
if (message.FilterReason != null) {
|
||||
if (message.Filtered) {
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
|
||||
|
@ -142,7 +151,7 @@ namespace NoSoliciting.Interface {
|
|||
var builder = new StringBuilder();
|
||||
|
||||
foreach (var message in this.Plugin.PartyFinderHistory) {
|
||||
if (message.FilterReason == null) {
|
||||
if (message.Classification == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -165,7 +174,7 @@ namespace NoSoliciting.Interface {
|
|||
foreach (var message in this.Plugin.PartyFinderHistory) {
|
||||
ImGui.TableNextRow();
|
||||
|
||||
if (message.FilterReason != null) {
|
||||
if (message.Filtered) {
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(238f / 255f, 71f / 255f, 71f / 255f, 1f));
|
||||
}
|
||||
|
||||
|
@ -175,11 +184,11 @@ namespace NoSoliciting.Interface {
|
|||
.Select(payload => payload.Text)
|
||||
.FirstOrDefault() ?? "";
|
||||
|
||||
if (AddRow(message.Timestamp.ToString(CultureInfo.CurrentCulture), message.FilterReason ?? "", sender, message.Content.TextValue)) {
|
||||
if (AddRow(message.Timestamp.ToString(CultureInfo.CurrentCulture), message.FilterReason ?? string.Empty, sender, message.Content.TextValue)) {
|
||||
ImGui.OpenPopup($"###modal-message-{message.Id}");
|
||||
}
|
||||
|
||||
if (message.FilterReason != null) {
|
||||
if (message.Filtered) {
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
|
||||
|
@ -197,50 +206,129 @@ namespace NoSoliciting.Interface {
|
|||
|
||||
#region Modal
|
||||
|
||||
private void SetUpReportModal(Message message) {
|
||||
private MessageCategory? _reportCategory;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns>true if modal is closing</returns>
|
||||
private bool SetUpReportModal(Message message) {
|
||||
var closing = false;
|
||||
|
||||
ImGui.SetNextWindowSize(new Vector2(350, -1));
|
||||
|
||||
var modalTitle = string.Format(Language.ReportModalTitle, this.Plugin.Name);
|
||||
if (!ImGui.BeginPopupModal($"{modalTitle}###modal-message-{message.Id}")) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._reportCategory == null) {
|
||||
if (message.Classification != null) {
|
||||
this._reportCategory = message.Classification;
|
||||
} else if (message.Classification == null && !message.Custom && !message.ItemLevel) {
|
||||
this._reportCategory = MessageCategory.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.PushTextWrapPos();
|
||||
|
||||
ImGui.TextUnformatted(Language.ReportModalHelp1);
|
||||
|
||||
ImGui.TextUnformatted(message.FilterReason != null
|
||||
? Language.ReportModalWasFiltered
|
||||
: Language.ReportModalWasNotFiltered);
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
ImGui.TextUnformatted(message.Content.TextValue);
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
ImGui.TextUnformatted(string.Format(Language.ReportModalOriginalClassification, message.FilterReason ?? MessageCategory.Normal.Name()));
|
||||
|
||||
ImGui.TextUnformatted(Language.ReportModalSuggestedClassification);
|
||||
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
if (ImGui.BeginCombo($"##modal-classification-{message.Id}", this._reportCategory?.Name() ?? string.Empty)) {
|
||||
foreach (var category in (MessageCategory[]) Enum.GetValues(typeof(MessageCategory))) {
|
||||
if (ImGui.Selectable($"{category.Name()}##modal-option-{message.Id}", this._reportCategory == category)) {
|
||||
this._reportCategory = category;
|
||||
}
|
||||
|
||||
if (!ImGui.IsItemHovered()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui.BeginTooltip();
|
||||
ImGui.PushTextWrapPos(ImGui.GetFontSize() * 24);
|
||||
ImGui.TextUnformatted(category.Description());
|
||||
ImGui.PopTextWrapPos();
|
||||
ImGui.EndTooltip();
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0f, 0f, 1f));
|
||||
ImGui.TextUnformatted(Language.ReportModalHelp2);
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
if (message.FilterReason == "custom") {
|
||||
string? errorText = null;
|
||||
if (message.Custom) {
|
||||
errorText = Language.ReportModalDisabledCustom;
|
||||
} else if (message.ItemLevel) {
|
||||
errorText = Language.ReportModalDisabledItemLevel;
|
||||
} else if (message.ModelVersion == null) {
|
||||
errorText = Language.ReportModalDisabledBadModel;
|
||||
} else if (this._reportCategory == message.Classification) {
|
||||
errorText = Language.ReportModalDisabledSameClassification;
|
||||
} else {
|
||||
switch (this.Plugin.Config.AdvancedMode) {
|
||||
case true when this.Plugin.Config.MlFilters.Values.All(set => set.Count == 0):
|
||||
case false when this.Plugin.Config.BasicMlFilters.Count == 0:
|
||||
errorText = Language.ReportModalDisabledNoFilters;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (errorText != null) {
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0f, 0f, 1f));
|
||||
ImGui.TextUnformatted(Language.ReportModalCustom);
|
||||
ImGui.TextUnformatted(errorText);
|
||||
ImGui.PopStyleColor();
|
||||
} else {
|
||||
var buttonTitle =Language.ReportModalReport;
|
||||
if (ImGui.Button($"{buttonTitle}##report-submit-{message.Id}")) {
|
||||
this.ReportMessage(message);
|
||||
if (ImGui.Button($"{Language.ReportModalReport}##report-submit-{message.Id}")) {
|
||||
var suggested = this._reportCategory?.ToModelName() ?? "none (this is a bug)";
|
||||
this._reportCategory = null;
|
||||
if (message == this.ToShowModal) {
|
||||
Task.Run(async () => {
|
||||
var status = await this.Plugin.Ui.Report.ReportMessageAsync(message, suggested);
|
||||
switch (status) {
|
||||
case ReportStatus.Successful: {
|
||||
var msg = Language.ReportToastSuccess;
|
||||
this.Plugin.Interface.Framework.Gui.Toast.ShowNormal(string.Format(msg, message.Sender));
|
||||
break;
|
||||
}
|
||||
case ReportStatus.Failure: {
|
||||
var msg = Language.ReportToastFailure;
|
||||
this.Plugin.Interface.Framework.Gui.Toast.ShowError(string.Format(msg, message.Sender));
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
this.ToShowModal = null;
|
||||
} else {
|
||||
this.ReportMessage(message, suggested);
|
||||
}
|
||||
|
||||
ImGui.CloseCurrentPopup();
|
||||
closing = true;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
var copyButton = Language.ReportModalCopy;
|
||||
if (ImGui.Button($"{copyButton}##report-copy-{message.Id}")) {
|
||||
if (ImGui.Button($"{Language.ReportModalCopy}##report-copy-{message.Id}")) {
|
||||
ImGui.SetClipboardText(message.Content.TextValue);
|
||||
}
|
||||
|
||||
|
@ -255,12 +343,20 @@ namespace NoSoliciting.Interface {
|
|||
|
||||
var cancelButton = Language.ReportModalCancel;
|
||||
if (ImGui.Button($"{cancelButton}##report-cancel-{message.Id}")) {
|
||||
this._reportCategory = null;
|
||||
if (message == this.ToShowModal) {
|
||||
this.ToShowModal = null;
|
||||
}
|
||||
|
||||
ImGui.CloseCurrentPopup();
|
||||
closing = true;
|
||||
}
|
||||
|
||||
ImGui.PopTextWrapPos();
|
||||
|
||||
ImGui.EndPopup();
|
||||
|
||||
return closing;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -292,18 +388,21 @@ namespace NoSoliciting.Interface {
|
|||
return clicked;
|
||||
}
|
||||
|
||||
internal void ReportMessage(Message message) {
|
||||
Task.Run(async () => await this.ReportMessageAsync(message));
|
||||
private void ReportMessage(Message message, string suggested) {
|
||||
Task.Run(async () => await this.ReportMessageAsync(message, suggested));
|
||||
}
|
||||
|
||||
internal async Task<ReportStatus> ReportMessageAsync(Message message) {
|
||||
private async Task<ReportStatus> ReportMessageAsync(Message message, string suggested) {
|
||||
string? resp = null;
|
||||
try {
|
||||
using var client = new WebClient();
|
||||
this.LastReportStatus = ReportStatus.InProgress;
|
||||
var reportUrl = this.Plugin.MlFilter?.ReportUrl;
|
||||
if (reportUrl != null) {
|
||||
resp = await client.UploadStringTaskAsync(reportUrl, message.ToJson()).ConfigureAwait(true);
|
||||
var json = message.ToJson(suggested);
|
||||
if (json != null) {
|
||||
resp = await client.UploadStringTaskAsync(reportUrl, json).ConfigureAwait(true);
|
||||
}
|
||||
}
|
||||
} catch (Exception) {
|
||||
// ignored
|
||||
|
|
|
@ -6,66 +6,87 @@ using System.Linq;
|
|||
using Dalamud.Data;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using NoSoliciting.Ml;
|
||||
|
||||
#if DEBUG
|
||||
using System.Text;
|
||||
using NoSoliciting.Ml;
|
||||
#endif
|
||||
|
||||
namespace NoSoliciting {
|
||||
[Serializable]
|
||||
public class Message {
|
||||
public Guid Id { get; }
|
||||
|
||||
[JsonIgnore]
|
||||
public uint ActorId { get; }
|
||||
public uint DefinitionsVersion { get; }
|
||||
|
||||
public uint? ModelVersion { get; }
|
||||
public DateTime Timestamp { get; }
|
||||
public ChatType ChatType { get; }
|
||||
public SeString Sender { get; }
|
||||
public SeString Content { get; }
|
||||
public bool Ml { get; }
|
||||
public string? FilterReason { get; }
|
||||
|
||||
public Message(uint defsVersion, ChatType type, uint actorId, SeString sender, SeString content, bool ml, string? reason) {
|
||||
public MessageCategory? Classification { get; }
|
||||
|
||||
public bool Custom { get; }
|
||||
public bool ItemLevel { get; }
|
||||
|
||||
public bool Filtered => this.Custom || this.ItemLevel || this.Classification != null;
|
||||
|
||||
public string? FilterReason => this.Custom
|
||||
? "custom"
|
||||
: this.ItemLevel
|
||||
? "ilvl"
|
||||
: this.Classification?.Name();
|
||||
|
||||
internal Message(uint? defsVersion, ChatType type, uint actorId, SeString sender, SeString content, MessageCategory? classification, bool custom, bool ilvl) {
|
||||
this.Id = Guid.NewGuid();
|
||||
this.DefinitionsVersion = defsVersion;
|
||||
this.ModelVersion = defsVersion;
|
||||
this.Timestamp = DateTime.Now;
|
||||
this.ChatType = type;
|
||||
this.ActorId = actorId;
|
||||
this.Sender = sender;
|
||||
this.Content = content;
|
||||
this.Ml = ml;
|
||||
this.FilterReason = reason;
|
||||
this.Classification = classification;
|
||||
this.Custom = custom;
|
||||
this.ItemLevel = ilvl;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[JsonObject(NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||
private class JsonMessage {
|
||||
public Guid Id { get; set; }
|
||||
public uint DefinitionsVersion { get; set; }
|
||||
public uint ReportVersion { get; } = 2;
|
||||
public uint ModelVersion { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
|
||||
public ushort Type { get; set; }
|
||||
|
||||
// note: cannot use byte[] because Newtonsoft thinks it's a good idea to always base64 byte[]
|
||||
// and I don't want to write a custom converter to overwrite their stupiditiy
|
||||
// and I don't want to write a custom converter to overwrite their stupidity
|
||||
public List<byte> Sender { get; set; }
|
||||
public List<byte> Content { get; set; }
|
||||
public bool Ml { get; set; }
|
||||
public string? Reason { get; set; }
|
||||
public string? SuggestedClassification { get; set; }
|
||||
}
|
||||
|
||||
public string ToJson() {
|
||||
public string? ToJson(string suggested) {
|
||||
if (this.ModelVersion == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var msg = new JsonMessage {
|
||||
Id = this.Id,
|
||||
DefinitionsVersion = this.DefinitionsVersion,
|
||||
ModelVersion = this.ModelVersion.Value,
|
||||
Timestamp = this.Timestamp,
|
||||
Type = (ushort) this.ChatType,
|
||||
Sender = this.Sender.Encode().ToList(),
|
||||
Content = this.Content.Encode().ToList(),
|
||||
Ml = this.Ml,
|
||||
Reason = this.FilterReason,
|
||||
Reason = this.Custom
|
||||
? "custom"
|
||||
: this.ItemLevel
|
||||
? "ilvl"
|
||||
: this.Classification?.ToModelName() ?? "unknown",
|
||||
SuggestedClassification = suggested,
|
||||
};
|
||||
|
||||
return JsonConvert.SerializeObject(msg, new JsonSerializerSettings {
|
||||
|
@ -77,9 +98,7 @@ namespace NoSoliciting {
|
|||
public StringBuilder ToCsv(StringBuilder? builder = null) {
|
||||
builder ??= new StringBuilder();
|
||||
|
||||
var category = MessageCategoryExt.FromName(this.FilterReason) ?? MessageCategory.Normal;
|
||||
|
||||
builder.Append(category.ToModelName());
|
||||
builder.Append(this.Classification?.ToModelName());
|
||||
builder.Append(',');
|
||||
builder.Append((int) this.ChatType);
|
||||
builder.Append(",\"");
|
||||
|
|
|
@ -43,20 +43,6 @@ namespace NoSoliciting.Ml {
|
|||
};
|
||||
|
||||
#if DEBUG
|
||||
public static string ToModelName(this MessageCategory category) => category switch {
|
||||
MessageCategory.Trade => "TRADE",
|
||||
MessageCategory.FreeCompany => "FC",
|
||||
MessageCategory.Normal => "NORMAL",
|
||||
MessageCategory.Phishing => "PHISH",
|
||||
MessageCategory.RmtContent => "RMT_C",
|
||||
MessageCategory.RmtGil => "RMT_G",
|
||||
MessageCategory.Roleplaying => "RP",
|
||||
MessageCategory.Static => "STATIC",
|
||||
MessageCategory.Community => "COMMUNITY",
|
||||
MessageCategory.StaticSub => "STATIC_SUB",
|
||||
_ => throw new ArgumentException("Invalid category", nameof(category)),
|
||||
};
|
||||
|
||||
public static MessageCategory? FromName(string? category) => category switch {
|
||||
"Trade ads" => MessageCategory.Trade,
|
||||
"Free Company ads" => MessageCategory.FreeCompany,
|
||||
|
@ -70,9 +56,22 @@ namespace NoSoliciting.Ml {
|
|||
"Static substitutes" => MessageCategory.StaticSub,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
public static string ToModelName(this MessageCategory category) => category switch {
|
||||
MessageCategory.Trade => "TRADE",
|
||||
MessageCategory.FreeCompany => "FC",
|
||||
MessageCategory.Normal => "NORMAL",
|
||||
MessageCategory.Phishing => "PHISH",
|
||||
MessageCategory.RmtContent => "RMT_C",
|
||||
MessageCategory.RmtGil => "RMT_G",
|
||||
MessageCategory.Roleplaying => "RP",
|
||||
MessageCategory.Static => "STATIC",
|
||||
MessageCategory.Community => "COMMUNITY",
|
||||
MessageCategory.StaticSub => "STATIC_SUB",
|
||||
_ => throw new ArgumentException("Invalid category", nameof(category)),
|
||||
};
|
||||
|
||||
public static string Name(this MessageCategory category) => category switch {
|
||||
MessageCategory.Trade => Language.TradeCategory,
|
||||
MessageCategory.FreeCompany => Language.FreeCompanyCategory,
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<PackageReference Include="JKang.IpcServiceFramework.Client.NamedPipe" Version="3.1.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1"/>
|
||||
<PackageReference Include="Resourcer.Fody" Version="1.8.0" PrivateAssets="all"/>
|
||||
<PackageReference Include="ResourcesMerge.Fody" Version="1.0.1" PrivateAssets="all"/>
|
||||
<PackageReference Include="ResourcesMerge.Fody" Version="1.0.3" PrivateAssets="all"/>
|
||||
<PackageReference Include="XivCommon" Version="1.5.0"/>
|
||||
<PackageReference Include="YamlDotNet" Version="11.1.1"/>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -474,12 +474,48 @@ namespace NoSoliciting.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Reporting is disabled because your ML model was not functioning when you saw this message..
|
||||
/// </summary>
|
||||
internal static string ReportModalDisabledBadModel {
|
||||
get {
|
||||
return ResourceManager.GetString("ReportModalDisabledBadModel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to You cannot report messages filtered because of a custom filter..
|
||||
/// </summary>
|
||||
internal static string ReportModalCustom {
|
||||
internal static string ReportModalDisabledCustom {
|
||||
get {
|
||||
return ResourceManager.GetString("ReportModalCustom", resourceCulture);
|
||||
return ResourceManager.GetString("ReportModalDisabledCustom", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to You cannot report messages filtered because of item level..
|
||||
/// </summary>
|
||||
internal static string ReportModalDisabledItemLevel {
|
||||
get {
|
||||
return ResourceManager.GetString("ReportModalDisabledItemLevel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Reporting is disabled because you do not have any filters enabled..
|
||||
/// </summary>
|
||||
internal static string ReportModalDisabledNoFilters {
|
||||
get {
|
||||
return ResourceManager.GetString("ReportModalDisabledNoFilters", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Reporting is disabled because you must choose a different classification than the original..
|
||||
/// </summary>
|
||||
internal static string ReportModalDisabledSameClassification {
|
||||
get {
|
||||
return ResourceManager.GetString("ReportModalDisabledSameClassification", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -501,6 +537,15 @@ namespace NoSoliciting.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This message's original classification: {0}.
|
||||
/// </summary>
|
||||
internal static string ReportModalOriginalClassification {
|
||||
get {
|
||||
return ResourceManager.GetString("ReportModalOriginalClassification", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Report.
|
||||
/// </summary>
|
||||
|
@ -510,6 +555,15 @@ namespace NoSoliciting.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to How do you think this message should have been classified?.
|
||||
/// </summary>
|
||||
internal static string ReportModalSuggestedClassification {
|
||||
get {
|
||||
return ResourceManager.GetString("ReportModalSuggestedClassification", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Report to {0}.
|
||||
/// </summary>
|
||||
|
|
|
@ -132,7 +132,7 @@
|
|||
<data name="ReportModalReport" xml:space="preserve">
|
||||
<value>Melden</value>
|
||||
</data>
|
||||
<data name="ReportModalCustom" xml:space="preserve">
|
||||
<data name="ReportModalDisabledCustom" xml:space="preserve">
|
||||
<value>Du kannst Nachrichten, die aufgrund von benutzerdefinierten Filtern gefiltert wurden, nicht melden.</value>
|
||||
</data>
|
||||
<data name="PhishingCategory" xml:space="preserve">
|
||||
|
|
|
@ -172,7 +172,7 @@
|
|||
<data name="ReportModalHelp2" xml:space="preserve">
|
||||
<value>NoSoliciting sólo funciona con mensajes en inglés. No informes de mensajes en otros idiomas.</value>
|
||||
</data>
|
||||
<data name="ReportModalCustom" xml:space="preserve">
|
||||
<data name="ReportModalDisabledCustom" xml:space="preserve">
|
||||
<value>No puedes informar de mensajes que han sido filtrados debido a un filtro personalizado.</value>
|
||||
</data>
|
||||
<data name="ReportModalReport" xml:space="preserve">
|
||||
|
|
|
@ -219,7 +219,7 @@
|
|||
<data name="ReportModalHelp2" xml:space="preserve">
|
||||
<value>NoSoliciting n'est fonctionnel que pour les messages en anglais. Veuillez ne pas signaler des messages qui ne sont pas en anglais.</value>
|
||||
</data>
|
||||
<data name="ReportModalCustom" xml:space="preserve">
|
||||
<data name="ReportModalDisabledCustom" xml:space="preserve">
|
||||
<value>Vous ne pouvez pas signaler de messages filtrés à cause d'un filtre personnalisé.</value>
|
||||
</data>
|
||||
<data name="ReportModalReport" xml:space="preserve">
|
||||
|
|
|
@ -172,7 +172,7 @@
|
|||
<data name="ReportModalHelp2" xml:space="preserve">
|
||||
<value>NoSolicitingは英語のメッセージにのみ有効です。 他の言語でメッセージを報告しないでください。</value>
|
||||
</data>
|
||||
<data name="ReportModalCustom" xml:space="preserve">
|
||||
<data name="ReportModalDisabledCustom" xml:space="preserve">
|
||||
<value>カスタムフィルタでフィルタリングされたメッセージを報告することはできません。</value>
|
||||
</data>
|
||||
<data name="ReportModalReport" xml:space="preserve">
|
||||
|
|
|
@ -181,7 +181,7 @@
|
|||
<data name="ReportModalWasNotFiltered" xml:space="preserve">
|
||||
<value>De maneira específica, essa mensagem NÃO FOI filtrada, mas deveria ter sido.</value>
|
||||
</data>
|
||||
<data name="ReportModalCustom" xml:space="preserve">
|
||||
<data name="ReportModalDisabledCustom" xml:space="preserve">
|
||||
<value>Voçê não pode relatar as mensagens filtradas por causa de um filtro personalizado.</value>
|
||||
</data>
|
||||
<data name="ReportModalReport" xml:space="preserve">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
|
||||
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
|
@ -153,7 +153,7 @@
|
|||
<data name="ReportModalHelp2" xml:space="preserve">
|
||||
<value>NoSoliciting only works for English messages. Do not report non-English messages.</value>
|
||||
</data>
|
||||
<data name="ReportModalCustom" xml:space="preserve">
|
||||
<data name="ReportModalDisabledCustom" xml:space="preserve">
|
||||
<value>You cannot report messages filtered because of a custom filter.</value>
|
||||
</data>
|
||||
<data name="ReportModalReport" xml:space="preserve">
|
||||
|
@ -255,4 +255,22 @@
|
|||
<data name="ModelStatusInitialised" xml:space="preserve">
|
||||
<value>Initialised</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="ReportModalDisabledBadModel" xml:space="preserve">
|
||||
<value>Reporting is disabled because your ML model was not functioning when you saw this message.</value>
|
||||
</data>
|
||||
<data name="ReportModalDisabledNoFilters" xml:space="preserve">
|
||||
<value>Reporting is disabled because you do not have any filters enabled.</value>
|
||||
</data>
|
||||
<data name="ReportModalDisabledSameClassification" xml:space="preserve">
|
||||
<value>Reporting is disabled because you must choose a different classification than the original.</value>
|
||||
</data>
|
||||
<data name="ReportModalDisabledItemLevel" xml:space="preserve">
|
||||
<value>You cannot report messages filtered because of item level.</value>
|
||||
</data>
|
||||
<data name="ReportModalOriginalClassification" xml:space="preserve">
|
||||
<value>This message's original classification: {0}</value>
|
||||
</data>
|
||||
<data name="ReportModalSuggestedClassification" xml:space="preserve">
|
||||
<value>How do you think this message should have been classified?</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
@ -175,7 +175,7 @@
|
|||
<data name="ReportModalWasNotFiltered" xml:space="preserve">
|
||||
<value>具体来说,这是一条应该被过滤的消息,但它被放过了。</value>
|
||||
</data>
|
||||
<data name="ReportModalCustom" xml:space="preserve">
|
||||
<data name="ReportModalDisabledCustom" xml:space="preserve">
|
||||
<value>你不能报告被自定义过滤规则过滤的消息。</value>
|
||||
</data>
|
||||
<data name="ReportModalReport" xml:space="preserve">
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
<data name="ReportModalHelp1" xml:space="preserve">
|
||||
<value>報告此消息將使開發人員知道此消息被錯誤歸類。</value>
|
||||
</data>
|
||||
<data name="ReportModalCustom" xml:space="preserve">
|
||||
<data name="ReportModalDisabledCustom" xml:space="preserve">
|
||||
<value>你不能報告被客製化過濾規則過濾的消息。</value>
|
||||
</data>
|
||||
<data name="OtherTab" xml:space="preserve">
|
||||
|
|
Loading…
Reference in New Issue