Compare commits

...

8 Commits

Author SHA1 Message Date
Anna f08baba71b
chore: bump version to 3.0.8 2023-10-03 17:35:46 -04:00
Anna 2804490fc6
refactor: update for api 9 2023-09-28 20:59:42 -04:00
Anna fae0b28d66
chore: bump version to 3.0.7 2023-09-03 18:12:20 -04:00
Anna 92e7ff8042 chore: bump version to 3.0.6 2023-01-15 15:09:04 -05:00
Anna 4bbae47da4 chore: update for 6.3 2023-01-15 15:08:30 -05:00
Anna dc9bb16054 chore: bump version to 3.0.5 2022-09-02 19:42:14 -04:00
Anna f87fb284e5 chore(trainer): update model 2022-09-01 03:39:03 -04:00
Anna 576634fa03 chore(trainer): change l1 and l2 regularisation 2022-08-29 22:10:33 -04:00
16 changed files with 1740 additions and 1121 deletions

View File

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6</TargetFramework>
<TargetFramework>net7</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="1.7.1"/>
<PackageReference Include="Microsoft.ML" Version="2.0.1" />
</ItemGroup>
</Project>

View File

@ -2,16 +2,15 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6</TargetFramework>
<TargetFramework>net7</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ConsoleTables" Version="2.4.2"/>
<PackageReference Include="CsvHelper" Version="28.0.1"/>
<PackageReference Include="Microsoft.ML" Version="1.7.1"/>
<PackageReference Include="MimeKitLite" Version="3.4.0"/>
<PackageReference Include="ConsoleTables" Version="2.5.0"/>
<PackageReference Include="CsvHelper" Version="30.0.1"/>
<PackageReference Include="Microsoft.ML" Version="2.0.1"/>
</ItemGroup>
<ItemGroup>

View File

@ -11,7 +11,6 @@ using CsvHelper.Configuration;
using Microsoft.ML;
using Microsoft.ML.Data;
using Microsoft.ML.Transforms.Text;
using MimeKit;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using NoSoliciting.Interface;
@ -21,6 +20,8 @@ namespace NoSoliciting.Trainer {
private static readonly string[] StopWords = {
"discord",
"gg",
"twitch",
"tv",
"lgbt",
"lgbtq",
"lgbtqia",
@ -40,7 +41,6 @@ namespace NoSoliciting.Trainer {
Interactive,
InteractiveFull,
Normalise,
Import,
}
[Serializable]
@ -56,51 +56,6 @@ namespace NoSoliciting.Trainer {
public string? SuggestedClassification { get; set; }
}
private static void Import(string path) {
var allData = new List<Data>();
var opts = new ParserOptions {
CharsetEncoding = Encoding.UTF8,
};
foreach (var emlPath in Directory.GetFiles(path, "*.eml")) {
var message = MimeMessage.Load(opts, new FileStream(emlPath, FileMode.Open));
var lines = message.TextBody
.Split('\r', '\n')
.SkipWhile(line => !line.StartsWith("JSON: "))
.Select(line => line.Replace("JSON: ", "").Replace(" ", "").Trim())
.ToArray();
if (lines.Length == 0) {
continue;
}
var json = string.Join("", lines);
var jsonText = Encoding.UTF8.GetString(Convert.FromBase64String(json));
var report = JsonConvert.DeserializeObject<ReportInput>(jsonText);
var content = XivString.GetText(report.Content);
var data = new Data(report.Type, content) {
Category = report.SuggestedClassification,
};
data.Message = data.Message
.Replace("\r\n", " ")
.Replace('\r', ' ')
.Replace('\n', ' ');
allData.Add(data);
}
var writer = new StringWriter();
using var csv = new CsvWriter(writer, new CsvConfiguration(CultureInfo.InvariantCulture) {
HeaderValidated = null,
Encoding = Encoding.UTF8,
});
csv.WriteRecords(allData
.OrderBy(data => data.Category)
.ThenBy(data => data.Channel)
.ThenBy(data => data.Message));
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine(writer.ToString());
}
private static void Main(string[] args) {
var mode = args[0] switch {
"test" => Mode.Test,
@ -108,15 +63,9 @@ namespace NoSoliciting.Trainer {
"interactive" => Mode.Interactive,
"interactive-full" => Mode.InteractiveFull,
"normalise" => Mode.Normalise,
"import" => Mode.Import,
_ => throw new ArgumentException("invalid argument"),
};
if (mode == Mode.Import) {
Import(args[1]);
return;
}
if (mode == Mode.Normalise) {
Console.WriteLine("Ready");
@ -225,7 +174,9 @@ namespace NoSoliciting.Trainer {
.Append(ctx.Transforms.Conversion.ConvertType("HasPlot", nameof(Data.Computed.ContainsPlot)))
.Append(ctx.Transforms.Conversion.ConvertType("HasNumbers", nameof(Data.Computed.ContainsHousingNumbers)))
.Append(ctx.Transforms.Concatenate("Features", "FeaturisedMessage", "CPartyFinder", "CShout", "CTrade", "HasWard", "HasPlot", "HasNumbers", "CSketch"))
.Append(ctx.MulticlassClassification.Trainers.SdcaMaximumEntropy(exampleWeightColumnName: "Weight"))
// macro 81.8 micro 84.6 (Tf weighting) - slow
// .Append(ctx.MulticlassClassification.Trainers.SdcaMaximumEntropy(exampleWeightColumnName: "Weight", l1Regularization: 0, l2Regularization: 0, maximumNumberOfIterations: 2_500))
.Append(ctx.MulticlassClassification.Trainers.SdcaMaximumEntropy(exampleWeightColumnName: "Weight", l1Regularization: 0, l2Regularization: 0, maximumNumberOfIterations: null))
.Append(ctx.Transforms.Conversion.MapKeyToValue("PredictedLabel"));
var train = mode switch {

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@ namespace NoSoliciting {
private void OnCommand(string command, string args) {
if (command == "/prmt") {
this.Plugin.ChatGui.PrintError($"[{this.Plugin.Name}] The /prmt command is deprecated and will be removed. Please use /nosol instead.");
this.Plugin.ChatGui.PrintError($"[{Plugin.Name}] The /prmt command is deprecated and will be removed. Please use /nosol instead.");
}
if (args == "report") {

View File

@ -2,7 +2,6 @@
using Dalamud.Game.Gui.PartyFinder.Types;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Logging;
using NoSoliciting.Interface;
using NoSoliciting.Ml;
@ -104,10 +103,10 @@ namespace NoSoliciting {
args.Visible = false;
if (this.Plugin.Config.LogFilteredPfs) {
PluginLog.Log($"Filtered PF listing from {listing.Name.TextValue} ({reason}): {listing.Description.TextValue}");
Plugin.Log.Info($"Filtered PF listing from {listing.Name.TextValue} ({reason}): {listing.Description.TextValue}");
}
} catch (Exception ex) {
PluginLog.LogError($"Error in PF listing event: {ex}");
Plugin.Log.Error($"Error in PF listing event: {ex}");
}
}
@ -166,7 +165,7 @@ namespace NoSoliciting {
this.Plugin.AddMessageHistory(history);
if (filter && this.Plugin.Config.LogFilteredChat) {
PluginLog.Log($"Filtered chat message ({history.FilterReason ?? "unknown"}): {text}");
Plugin.Log.Info($"Filtered chat message ({history.FilterReason ?? "unknown"}): {text}");
}
return filter;
@ -202,7 +201,7 @@ namespace NoSoliciting {
var category = this.Plugin.MlFilter.ClassifyMessage((ushort) ChatType.None, desc);
if (category != MessageCategory.Normal && this.Plugin.Config.MlEnabledOn(category, ChatType.None)) {
return (category, null);
return (category, Enum.GetName(category));
}
return (null, null);

View File

@ -1,9 +1,9 @@
using Dalamud.Data;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel.GeneratedSheets;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Dalamud.Plugin.Services;
using NoSoliciting.Ml;
namespace NoSoliciting {
@ -87,7 +87,7 @@ namespace NoSoliciting {
return null;
}
public static int MaxItemLevelAttainable(DataManager data) {
public static int MaxItemLevelAttainable(IDataManager data) {
if (MaxItemLevel > 0) {
return MaxItemLevel;
}

View File

@ -6,7 +6,6 @@ using System.Numerics;
using System.Threading.Tasks;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Logging;
using ImGuiNET;
using NoSoliciting.Ml;
using NoSoliciting.Resources;
@ -66,7 +65,7 @@ namespace NoSoliciting.Interface {
ImGui.SetNextWindowSize(new Vector2(1_000, 350), ImGuiCond.FirstUseEver);
var windowTitle = string.Format(Language.Reporting, this.Plugin.Name);
var windowTitle = string.Format(Language.Reporting, Plugin.Name);
if (!ImGui.Begin($"{windowTitle}###NoSoliciting reporting", ref this._showReporting)) {
ImGui.End();
return;
@ -224,7 +223,7 @@ namespace NoSoliciting.Interface {
ImGui.SetNextWindowSize(new Vector2(350, -1));
var modalTitle = string.Format(Language.ReportModalTitle, this.Plugin.Name);
var modalTitle = string.Format(Language.ReportModalTitle, Plugin.Name);
if (!ImGui.BeginPopupModal($"{modalTitle}###modal-message-{message.Id}")) {
return false;
}
@ -441,11 +440,11 @@ namespace NoSoliciting.Interface {
var status = resp == "{\"message\":\"ok\"}" ? ReportStatus.Successful : ReportStatus.Failure;
if (status == ReportStatus.Failure) {
PluginLog.LogWarning($"Failed to report message:\n{resp}");
Plugin.Log.Warning($"Failed to report message:\n{resp}");
}
this.LastReportStatus = status;
PluginLog.Log(resp == null
Plugin.Log.Info(resp == null
? "Report not sent. ML model not set."
: $"Report sent. Response: {resp}");

View File

@ -44,7 +44,7 @@ namespace NoSoliciting.Interface {
}
public void Draw() {
var windowTitle = string.Format(Language.Settings, this.Plugin.Name);
var windowTitle = string.Format(Language.Settings, Plugin.Name);
if (!this.ShowSettings || !ImGui.Begin($"{windowTitle}###NoSoliciting settings", ref this._showSettings)) {
return;
}

View File

@ -3,9 +3,9 @@ using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Data;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.Services;
using Lumina.Excel.GeneratedSheets;
using NoSoliciting.Ml;
@ -208,7 +208,7 @@ namespace NoSoliciting {
_ => (byte) type,
};
public static string Name(this ChatType type, DataManager data) {
public static string Name(this ChatType type, IDataManager data) {
switch (type) {
case ChatType.None:
return "Party Finder";

View File

@ -5,7 +5,6 @@ using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Dalamud.Logging;
using NoSoliciting.Interface;
using NoSoliciting.Resources;
using YamlDotNet.Core;
@ -43,7 +42,7 @@ namespace NoSoliciting.Ml {
return (MessageCategory) category;
}
PluginLog.LogWarning($"Unknown message category: {prediction}");
Plugin.Log.Warning($"Unknown message category: {prediction}");
return MessageCategory.Normal;
}
@ -53,7 +52,7 @@ namespace NoSoliciting.Ml {
// download and parse the remote manifest
var manifest = await DownloadManifest();
if (manifest == null) {
PluginLog.LogWarning("Could not download manifest. Will attempt to fall back on cached version.");
Plugin.Log.Warning("Could not download manifest. Will attempt to fall back on cached version.");
}
// model zip file data
@ -96,7 +95,7 @@ namespace NoSoliciting.Ml {
var hash = sha.ComputeHash(data);
while (!hash.SequenceEqual(correctHash) && retries < maxRetries) {
PluginLog.Warning($"Model checksum did not match. Redownloading (attempt {retries + 1}/{maxRetries})");
Plugin.Log.Warning($"Model checksum did not match. Redownloading (attempt {retries + 1}/{maxRetries})");
retries += 1;
data = await DownloadModel(manifest!.Value.manifest!.ModelUrl);
@ -138,8 +137,8 @@ namespace NoSoliciting.Ml {
var data = await client.DownloadDataTaskAsync(url);
return data;
} catch (WebException e) {
PluginLog.LogError("Could not download newest model.");
PluginLog.LogError(e.ToString());
Plugin.Log.Error("Could not download newest model.");
Plugin.Log.Error(e.ToString());
LastError = e.Message;
return null;
}
@ -167,8 +166,8 @@ namespace NoSoliciting.Ml {
LastError = null;
return (LoadYaml<Manifest>(data), data);
} catch (Exception e) when (e is WebException or YamlException) {
PluginLog.LogError("Could not download newest model manifest.");
PluginLog.LogError(e.ToString());
Plugin.Log.Error("Could not download newest model manifest.");
Plugin.Log.Error(e.ToString());
LastError = e.Message;
return null;
}

View File

@ -3,8 +3,8 @@
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<Version>3.0.3</Version>
<TargetFramework>net6-windows</TargetFramework>
<Version>3.0.8</Version>
<TargetFramework>net7-windows</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x64</PlatformTarget>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
@ -47,13 +47,13 @@
</Reference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Dalamud.ContextMenu" Version="1.2.0"/>
<PackageReference Include="DalamudPackager" Version="2.1.8"/>
<PackageReference Include="Fody" Version="6.6.3" PrivateAssets="all"/>
<PackageReference Include="Microsoft.ML" Version="1.7.1"/>
<PackageReference Include="Resourcer.Fody" Version="1.8.0" PrivateAssets="all"/>
<PackageReference Include="XivCommon" Version="6.0.0"/>
<PackageReference Include="YamlDotNet" Version="12.0.0"/>
<PackageReference Include="Dalamud.ContextMenu" Version="1.3.1"/>
<PackageReference Include="DalamudPackager" Version="2.1.12"/>
<PackageReference Include="Fody" Version="6.8.0" PrivateAssets="all"/>
<PackageReference Include="Microsoft.ML" Version="2.0.1"/>
<PackageReference Include="Resourcer.Fody" Version="1.8.1" PrivateAssets="all"/>
<PackageReference Include="XivCommon" Version="9.0.0"/>
<PackageReference Include="YamlDotNet" Version="13.4.0"/>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\Language.resx">

View File

@ -1,4 +1,4 @@
author: ascclemens
author: Anna
name: NoSoliciting
punchline: Adblock for FFXIV.
description: |-
@ -14,6 +14,6 @@ description: |-
- Trade ads
- Community ads
- Any PF with an item level over the max
repo_url: https://git.sr.ht/~jkcclemens/NoSoliciting
repo_url: https://git.anna.lgbt/anna/NoSoliciting
# Use higher priority to filter messages before other plugins get them.
load_priority: 100

View File

@ -7,14 +7,8 @@ using System.Reflection;
using System.Threading.Tasks;
using Dalamud;
using Dalamud.ContextMenu;
using Dalamud.Data;
using Dalamud.Game.ClientState;
using Dalamud.Game.Command;
using Dalamud.Game.Gui;
using Dalamud.Game.Gui.PartyFinder;
using Dalamud.Game.Gui.Toast;
using Dalamud.IoC;
using Dalamud.Logging;
using Dalamud.Plugin.Services;
using NoSoliciting.Interface;
using NoSoliciting.Ml;
using NoSoliciting.Resources;
@ -25,30 +19,33 @@ namespace NoSoliciting {
public class Plugin : IDalamudPlugin {
private bool _disposedValue;
public string Name => "NoSoliciting";
internal static string Name => "NoSoliciting";
private Filter Filter { get; }
[PluginService]
internal static IPluginLog Log { get; private set; } = null!;
[PluginService]
internal DalamudPluginInterface Interface { get; init; } = null!;
[PluginService]
private ClientState ClientState { get; init; } = null!;
private IClientState ClientState { get; init; } = null!;
[PluginService]
internal ChatGui ChatGui { get; init; } = null!;
internal IChatGui ChatGui { get; init; } = null!;
[PluginService]
internal PartyFinderGui PartyFinderGui { get; init; } = null!;
internal IPartyFinderGui PartyFinderGui { get; init; } = null!;
[PluginService]
internal DataManager DataManager { get; init; } = null!;
internal IDataManager DataManager { get; init; } = null!;
[PluginService]
internal CommandManager CommandManager { get; init; } = null!;
internal ICommandManager CommandManager { get; init; } = null!;
[PluginService]
internal ToastGui ToastGui { get; init; } = null!;
internal IToastGui ToastGui { get; init; } = null!;
internal PluginConfiguration Config { get; }
internal XivCommonBase Common { get; }
@ -80,8 +77,8 @@ namespace NoSoliciting {
this.ConfigureLanguage();
this.Interface.LanguageChanged += this.OnLanguageUpdate;
this.Common = new XivCommonBase(Hooks.PartyFinderListings);
this.DalamudContextMenu = new DalamudContextMenu();
this.Common = new XivCommonBase(this.Interface, Hooks.PartyFinderListings);
this.DalamudContextMenu = new DalamudContextMenu(this.Interface);
this.Ui = new PluginUi(this);
this.Commands = new Commands(this);
@ -95,7 +92,7 @@ namespace NoSoliciting {
try {
FilterUtil.MaxItemLevelAttainable(this.DataManager);
} catch (Exception ex) {
PluginLog.LogError(ex, "Exception while computing max item level");
Plugin.Log.Error(ex, "Exception while computing max item level");
}
}
@ -152,7 +149,7 @@ namespace NoSoliciting {
}
this.MlStatus = MlFilterStatus.Initialised;
PluginLog.Log("Machine learning model loaded");
Log.Info("Machine learning model loaded");
});
}

View File

@ -44,13 +44,17 @@ namespace NoSoliciting {
public Dictionary<MessageCategory, HashSet<ChatType>> MlFilters { get; set; } = new() {
[MessageCategory.RmtGil] = new HashSet<ChatType> {
ChatType.None,
ChatType.Say,
ChatType.Shout,
},
[MessageCategory.RmtContent] = new HashSet<ChatType> {
ChatType.None,
ChatType.Say,
ChatType.Shout,
},
[MessageCategory.Phishing] = new HashSet<ChatType> {
ChatType.None,
ChatType.TellIncoming,
},
[MessageCategory.Roleplaying] = new HashSet<ChatType> {
@ -72,12 +76,18 @@ namespace NoSoliciting {
},
[MessageCategory.Trade] = new HashSet<ChatType> {
ChatType.None,
ChatType.Shout,
ChatType.Yell,
},
[MessageCategory.Community] = new HashSet<ChatType> {
ChatType.None,
ChatType.Shout,
ChatType.Yell,
},
[MessageCategory.Fluff] = new HashSet<ChatType> {
ChatType.None,
ChatType.Shout,
ChatType.Yell,
},
};

File diff suppressed because it is too large Load Diff