feat: allow specifying main filters dynamically
Main filters (e.g. RMT, RP, FC) can now be fully specified by the definitions file, allowing entire new classes of filters to be added without a plugin update.
This commit is contained in:
parent
853d39faf0
commit
ec2bfc03d0
|
@ -1,4 +1,5 @@
|
|||
using Dalamud.Plugin;
|
||||
using Dalamud.Game.Chat;
|
||||
using Dalamud.Plugin;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
@ -21,9 +22,11 @@ namespace NoSoliciting {
|
|||
private const string URL = "https://git.sr.ht/~jkcclemens/NoSoliciting/blob/master/NoSoliciting/definitions.yaml";
|
||||
|
||||
public uint Version { get; private set; }
|
||||
public ChatDefinitions Chat { get; private set; }
|
||||
public PartyFinderDefinitions PartyFinder { get; private set; }
|
||||
public GlobalDefinitions Global { get; private set; }
|
||||
[YamlIgnore]
|
||||
public int Count { get => this.Chat.Count + this.PartyFinder.Count + this.Global.Count; }
|
||||
public Dictionary<string, Definition> Chat { get; private set; }
|
||||
public Dictionary<string, Definition> PartyFinder { get; private set; }
|
||||
public Dictionary<string, Definition> Global { get; private set; }
|
||||
|
||||
public static async Task<Definitions> UpdateAndCache(Plugin plugin) {
|
||||
Definitions defs = null;
|
||||
|
@ -128,51 +131,61 @@ namespace NoSoliciting {
|
|||
}
|
||||
}
|
||||
|
||||
internal void Initialise() {
|
||||
Definition[] all = {
|
||||
this.Chat.RMT,
|
||||
this.Chat.FreeCompany,
|
||||
this.PartyFinder.RMT,
|
||||
this.Global.Roleplay,
|
||||
};
|
||||
internal void Initialise(Plugin plugin) {
|
||||
IEnumerable<KeyValuePair<string, Definition>> defs = this.Chat.Select(e => new KeyValuePair<string, Definition>($"chat.{e.Key}", e.Value))
|
||||
.Concat(this.PartyFinder.Select(e => new KeyValuePair<string, Definition>($"party_finder.{e.Key}", e.Value)));
|
||||
|
||||
foreach (Definition def in all) {
|
||||
def.Initialise();
|
||||
foreach (KeyValuePair<string, Definition> entry in defs) {
|
||||
entry.Value.Initialise(entry.Key);
|
||||
if (!plugin.Config.FilterStatus.TryGetValue(entry.Key, out _)) {
|
||||
plugin.Config.FilterStatus[entry.Key] = entry.Value.Default;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, Definition> entry in this.Global) {
|
||||
Definition chat = entry.Value.Clone();
|
||||
chat.Initialise($"chat.global.{entry.Key}");
|
||||
this.Chat[$"global.{entry.Key}"] = chat;
|
||||
|
||||
Definition pf = entry.Value.Clone();
|
||||
pf.Initialise($"party_finder.global.{entry.Key}");
|
||||
this.PartyFinder[$"global.{entry.Key}"] = pf;
|
||||
|
||||
if (!plugin.Config.FilterStatus.TryGetValue(chat.Id, out _)) {
|
||||
plugin.Config.FilterStatus[chat.Id] = chat.Default;
|
||||
}
|
||||
if (!plugin.Config.FilterStatus.TryGetValue(pf.Id, out _)) {
|
||||
plugin.Config.FilterStatus[pf.Id] = pf.Default;
|
||||
}
|
||||
}
|
||||
|
||||
plugin.Config.Save();
|
||||
}
|
||||
}
|
||||
|
||||
public class ChatDefinitions {
|
||||
[YamlMember(Alias = "rmt")]
|
||||
public Definition RMT { get; private set; }
|
||||
public Definition FreeCompany { get; private set; }
|
||||
}
|
||||
|
||||
public class PartyFinderDefinitions {
|
||||
[YamlMember(Alias = "rmt")]
|
||||
public Definition RMT { get; private set; }
|
||||
}
|
||||
|
||||
public class GlobalDefinitions {
|
||||
public Definition Roleplay { get; private set; }
|
||||
}
|
||||
|
||||
public class Definition {
|
||||
private bool initialised = false;
|
||||
|
||||
[YamlIgnore]
|
||||
public string Id { get; private set; }
|
||||
public List<List<Matcher>> RequiredMatchers { get; private set; } = new List<List<Matcher>>();
|
||||
public List<List<Matcher>> LikelyMatchers { get; private set; } = new List<List<Matcher>>();
|
||||
public int LikelihoodThreshold { get; private set; } = 0;
|
||||
public bool IgnoreCase { get; private set; } = false;
|
||||
public bool Normalise { get; private set; } = true;
|
||||
public List<XivChatType> Channels { get; private set; } = new List<XivChatType>();
|
||||
public OptionNames Option { get; private set; }
|
||||
public bool Default { get; private set; } = false;
|
||||
|
||||
internal void Initialise() {
|
||||
internal void Initialise(string id) {
|
||||
if (this.initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initialised = true;
|
||||
|
||||
this.Id = id ?? throw new ArgumentNullException(nameof(id), "string cannot be null");
|
||||
|
||||
if (!this.IgnoreCase) {
|
||||
return;
|
||||
}
|
||||
|
@ -186,11 +199,15 @@ namespace NoSoliciting {
|
|||
}
|
||||
}
|
||||
|
||||
public bool Matches(string text) {
|
||||
public bool Matches(XivChatType type, string text) {
|
||||
if (text == null) {
|
||||
throw new ArgumentNullException(nameof(text), "string cannot be null");
|
||||
}
|
||||
|
||||
if (this.Channels.Count != 0 && !this.Channels.Contains(type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.Normalise) {
|
||||
text = RMTUtil.Normalise(text);
|
||||
}
|
||||
|
@ -217,6 +234,19 @@ namespace NoSoliciting {
|
|||
// matches only if likelihood is greater than or equal the threshold
|
||||
return likelihood >= this.LikelihoodThreshold;
|
||||
}
|
||||
|
||||
public Definition Clone() {
|
||||
return new Definition {
|
||||
RequiredMatchers = this.RequiredMatchers,
|
||||
LikelyMatchers = this.LikelyMatchers,
|
||||
LikelihoodThreshold = this.LikelihoodThreshold,
|
||||
IgnoreCase = this.IgnoreCase,
|
||||
Normalise = this.Normalise,
|
||||
Channels = this.Channels,
|
||||
Option = this.Option,
|
||||
Default = this.Default,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class Matcher {
|
||||
|
@ -258,6 +288,11 @@ namespace NoSoliciting {
|
|||
}
|
||||
}
|
||||
|
||||
public class OptionNames {
|
||||
public string Basic { get; private set; }
|
||||
public string Advanced { get; private set; }
|
||||
}
|
||||
|
||||
internal sealed class MatcherConverter : IYamlTypeConverter {
|
||||
public bool Accepts(Type type) {
|
||||
return type == typeof(Matcher);
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace NoSoliciting {
|
|||
Definitions defs = await Definitions.UpdateAndCache(this).ConfigureAwait(true);
|
||||
// this shouldn't be possible, but what do I know
|
||||
if (defs != null) {
|
||||
defs.Initialise();
|
||||
defs.Initialise(this);
|
||||
this.Definitions = defs;
|
||||
Definitions.LastUpdate = DateTime.Now;
|
||||
}
|
||||
|
|
|
@ -11,13 +11,20 @@ namespace NoSoliciting {
|
|||
|
||||
public int Version { get; set; } = 1;
|
||||
|
||||
[Obsolete("Use EnabledFilters")]
|
||||
public bool FilterChat { get; set; } = true;
|
||||
[Obsolete("Use EnabledFilters")]
|
||||
public bool FilterFCRecruitments { get; set; } = false;
|
||||
[Obsolete("Use EnabledFilters")]
|
||||
public bool FilterChatRPAds { get; set; } = false;
|
||||
|
||||
[Obsolete("Use EnabledFilters")]
|
||||
public bool FilterPartyFinder { get; set; } = true;
|
||||
[Obsolete("Use EnabledFilters")]
|
||||
public bool FilterPartyFinderRPAds { get; set; } = false;
|
||||
|
||||
public Dictionary<string, bool> FilterStatus { get; private set; } = new Dictionary<string, bool>();
|
||||
|
||||
public bool AdvancedMode { get; set; } = false;
|
||||
|
||||
public bool CustomChatFilter { get; set; } = false;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using ImGuiNET;
|
||||
using Dalamud.Interface;
|
||||
using ImGuiNET;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
@ -7,6 +8,7 @@ using System.Text.RegularExpressions;
|
|||
namespace NoSoliciting {
|
||||
public class PluginUI {
|
||||
private readonly Plugin plugin;
|
||||
private bool resizeWindow = false;
|
||||
|
||||
private bool _showSettings;
|
||||
public bool ShowSettings { get => this._showSettings; set => this._showSettings = value; }
|
||||
|
@ -26,6 +28,12 @@ namespace NoSoliciting {
|
|||
}
|
||||
|
||||
public void DrawSettings() {
|
||||
if (this.resizeWindow) {
|
||||
this.resizeWindow = false;
|
||||
ImGui.SetNextWindowSize(new Vector2(this.plugin.Config.AdvancedMode ? 600 : 0, 0));
|
||||
} else {
|
||||
ImGui.SetNextWindowSize(new Vector2(0, 0), ImGuiCond.FirstUseEver);
|
||||
}
|
||||
if (ImGui.Begin($"{this.plugin.Name} settings", ref this._showSettings)) {
|
||||
if (this.plugin.Config.AdvancedMode) {
|
||||
this.DrawAdvancedSettings();
|
||||
|
@ -39,6 +47,7 @@ namespace NoSoliciting {
|
|||
if (ImGui.Checkbox("Advanced mode", ref advanced)) {
|
||||
this.plugin.Config.AdvancedMode = advanced;
|
||||
this.plugin.Config.Save();
|
||||
resizeWindow = true;
|
||||
}
|
||||
|
||||
ImGui.End();
|
||||
|
@ -46,105 +55,55 @@ namespace NoSoliciting {
|
|||
}
|
||||
|
||||
private void DrawBasicSettings() {
|
||||
ImGui.SetWindowSize(new Vector2(250, 225));
|
||||
|
||||
bool filterChat = this.plugin.Config.FilterChat;
|
||||
if (ImGui.Checkbox("Filter RMT from chat", ref filterChat)) {
|
||||
this.plugin.Config.FilterChat = filterChat;
|
||||
this.plugin.Config.Save();
|
||||
if (this.plugin.Definitions == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool filterFC = this.plugin.Config.FilterFCRecruitments;
|
||||
if (ImGui.Checkbox("Filter FC recruitments from chat", ref filterFC)) {
|
||||
this.plugin.Config.FilterFCRecruitments = filterFC;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
|
||||
bool filterChatRP = this.plugin.Config.FilterChatRPAds;
|
||||
if (ImGui.Checkbox("Filter RP ads from chat", ref filterChatRP)) {
|
||||
this.plugin.Config.FilterChatRPAds = filterChatRP;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
this.DrawCheckboxes(this.plugin.Definitions.Chat.Values, true, "chat");
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
bool filterPartyFinder = this.plugin.Config.FilterPartyFinder;
|
||||
if (ImGui.Checkbox("Filter RMT from Party Finder", ref filterPartyFinder)) {
|
||||
this.plugin.Config.FilterPartyFinder = filterPartyFinder;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
|
||||
bool filterPFRP = this.plugin.Config.FilterPartyFinderRPAds;
|
||||
if (ImGui.Checkbox("Filter RP ads from Party Finder", ref filterPFRP)) {
|
||||
this.plugin.Config.FilterPartyFinderRPAds = filterPFRP;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
this.DrawCheckboxes(this.plugin.Definitions.PartyFinder.Values, true, "Party Finder");
|
||||
}
|
||||
|
||||
private void DrawAdvancedSettings() {
|
||||
ImGui.SetWindowSize(new Vector2(600, 450));
|
||||
|
||||
if (ImGui.BeginTabBar("##nosoliciting-tabs")) {
|
||||
if (ImGui.BeginTabItem("Chat")) {
|
||||
bool filterChat = this.plugin.Config.FilterChat;
|
||||
if (ImGui.Checkbox("Enable built-in RMT filter", ref filterChat)) {
|
||||
this.plugin.Config.FilterChat = filterChat;
|
||||
this.plugin.Config.Save();
|
||||
if (this.plugin.Definitions != null) {
|
||||
if (ImGui.BeginTabItem("Chat")) {
|
||||
this.DrawCheckboxes(this.plugin.Definitions.Chat.Values, false, "chat");
|
||||
|
||||
bool customChat = this.plugin.Config.CustomChatFilter;
|
||||
if (ImGui.Checkbox("Enable custom chat filters", ref customChat)) {
|
||||
this.plugin.Config.CustomChatFilter = customChat;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
|
||||
if (this.plugin.Config.CustomChatFilter) {
|
||||
List<string> substrings = this.plugin.Config.ChatSubstrings;
|
||||
List<string> regexes = this.plugin.Config.ChatRegexes;
|
||||
this.DrawCustom("chat", ref substrings, ref regexes);
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
bool filterFC = this.plugin.Config.FilterFCRecruitments;
|
||||
if (ImGui.Checkbox("Enable built-in FC recruitment filter", ref filterFC)) {
|
||||
this.plugin.Config.FilterFCRecruitments = filterFC;
|
||||
this.plugin.Config.Save();
|
||||
if (ImGui.BeginTabItem("Party Finder")) {
|
||||
this.DrawCheckboxes(this.plugin.Definitions.PartyFinder.Values, false, "Party Finder");
|
||||
|
||||
bool customPF = this.plugin.Config.CustomPFFilter;
|
||||
if (ImGui.Checkbox("Enable custom Party Finder filters", ref customPF)) {
|
||||
this.plugin.Config.CustomPFFilter = customPF;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
|
||||
if (this.plugin.Config.CustomPFFilter) {
|
||||
List<string> substrings = this.plugin.Config.PFSubstrings;
|
||||
List<string> regexes = this.plugin.Config.PFRegexes;
|
||||
this.DrawCustom("pf", ref substrings, ref regexes);
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
bool filterChatRP = this.plugin.Config.FilterChatRPAds;
|
||||
if (ImGui.Checkbox("Enable built-in RP ad filter", ref filterChatRP)) {
|
||||
this.plugin.Config.FilterChatRPAds = filterChatRP;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
|
||||
bool customChat = this.plugin.Config.CustomChatFilter;
|
||||
if (ImGui.Checkbox("Enable custom chat filters", ref customChat)) {
|
||||
this.plugin.Config.CustomChatFilter = customChat;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
|
||||
if (this.plugin.Config.CustomChatFilter) {
|
||||
List<string> substrings = this.plugin.Config.ChatSubstrings;
|
||||
List<string> regexes = this.plugin.Config.ChatRegexes;
|
||||
this.DrawCustom("chat", ref substrings, ref regexes);
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui.BeginTabItem("Party Finder")) {
|
||||
bool filterPartyFinder = this.plugin.Config.FilterPartyFinder;
|
||||
if (ImGui.Checkbox("Enable built-in Party Finder RMT filter", ref filterPartyFinder)) {
|
||||
this.plugin.Config.FilterPartyFinder = filterPartyFinder;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
|
||||
bool filterPFRP = this.plugin.Config.FilterPartyFinderRPAds;
|
||||
if (ImGui.Checkbox("Enable built-in Party Finder RP filter", ref filterPFRP)) {
|
||||
this.plugin.Config.FilterPartyFinderRPAds = filterPFRP;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
|
||||
bool customPF = this.plugin.Config.CustomPFFilter;
|
||||
if (ImGui.Checkbox("Enable custom Party Finder filters", ref customPF)) {
|
||||
this.plugin.Config.CustomPFFilter = customPF;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
|
||||
if (this.plugin.Config.CustomPFFilter) {
|
||||
List<string> substrings = this.plugin.Config.PFSubstrings;
|
||||
List<string> regexes = this.plugin.Config.PFRegexes;
|
||||
this.DrawCustom("pf", ref substrings, ref regexes);
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui.BeginTabItem("Definitions")) {
|
||||
|
@ -177,20 +136,24 @@ namespace NoSoliciting {
|
|||
if (ImGui.BeginChild($"##{name}-substrings", new Vector2(0, 175))) {
|
||||
for (int i = 0; i < substrings.Count; i++) {
|
||||
string input = substrings[i];
|
||||
if (ImGui.InputText($"##{name}-substring-{i}", ref input, 100)) {
|
||||
if (ImGui.InputText($"##{name}-substring-{i}", ref input, 1_000)) {
|
||||
if (input.Length != 0) {
|
||||
substrings[i] = input;
|
||||
}
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button($"Remove##{name}-substring-{i}-remove")) {
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (ImGui.Button($"{FontAwesomeIcon.Trash.ToIconString()}##{name}-substring-{i}-remove")) {
|
||||
substrings.RemoveAt(i);
|
||||
}
|
||||
ImGui.PopFont();
|
||||
}
|
||||
|
||||
if (ImGui.Button($"Add##{name}-substring-add")) {
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (ImGui.Button($"{FontAwesomeIcon.Plus.ToIconString()}##{name}-substring-add")) {
|
||||
substrings.Add("");
|
||||
}
|
||||
ImGui.PopFont();
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
@ -201,7 +164,7 @@ namespace NoSoliciting {
|
|||
if (ImGui.BeginChild($"##{name}-regexes", new Vector2(0, 175))) {
|
||||
for (int i = 0; i < regexes.Count; i++) {
|
||||
string input = regexes[i];
|
||||
if (ImGui.InputText($"##{name}-regex-{i}", ref input, 100)) {
|
||||
if (ImGui.InputText($"##{name}-regex-{i}", ref input, 1_000)) {
|
||||
bool valid = true;
|
||||
try {
|
||||
_ = new Regex(input);
|
||||
|
@ -213,14 +176,18 @@ namespace NoSoliciting {
|
|||
}
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button($"Remove##{name}-regex-{i}-remove")) {
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (ImGui.Button($"{FontAwesomeIcon.Trash.ToIconString()}##{name}-regex-{i}-remove")) {
|
||||
regexes.RemoveAt(i);
|
||||
}
|
||||
ImGui.PopFont();
|
||||
}
|
||||
|
||||
if (ImGui.Button($"Add##{name}-regex-add")) {
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (ImGui.Button($"{FontAwesomeIcon.Plus.ToIconString()}##{name}-regex-add")) {
|
||||
regexes.Add("");
|
||||
}
|
||||
ImGui.PopFont();
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
@ -231,5 +198,17 @@ namespace NoSoliciting {
|
|||
this.plugin.Config.Save();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCheckboxes(IEnumerable<Definition> defs, bool basic, string labelFillIn) {
|
||||
foreach (Definition def in defs) {
|
||||
this.plugin.Config.FilterStatus.TryGetValue(def.Id, out bool enabled);
|
||||
string label = basic ? def.Option.Basic : def.Option.Advanced;
|
||||
label = label.Replace("{}", labelFillIn);
|
||||
if (ImGui.Checkbox(label, ref enabled)) {
|
||||
this.plugin.Config.FilterStatus[def.Id] = enabled;
|
||||
this.plugin.Config.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ using Dalamud.Game.Chat.SeStringHandling;
|
|||
using Dalamud.Game.Internal.Network;
|
||||
using Dalamud.Plugin;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NoSoliciting {
|
||||
|
@ -23,11 +22,6 @@ namespace NoSoliciting {
|
|||
return;
|
||||
}
|
||||
|
||||
bool anyFilter = this.plugin.Config.FilterPartyFinder || this.plugin.Config.FilterPartyFinderRPAds || this.plugin.Config.CustomPFFilter;
|
||||
if (!anyFilter) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only look at packets coming in
|
||||
if (direction != NetworkMessageDirection.ZoneDown) {
|
||||
return;
|
||||
|
@ -53,10 +47,12 @@ namespace NoSoliciting {
|
|||
|
||||
bool filter = false;
|
||||
|
||||
// check for RMT if enabled
|
||||
filter |= this.plugin.Config.FilterPartyFinder && this.plugin.Definitions.PartyFinder.RMT.Matches(desc);
|
||||
// check for RP if enabled
|
||||
filter |= this.plugin.Config.FilterPartyFinderRPAds && this.plugin.Definitions.Global.Roleplay.Matches(desc);
|
||||
foreach (Definition def in this.plugin.Definitions.PartyFinder.Values) {
|
||||
filter |= this.plugin.Config.FilterStatus.TryGetValue(def.Id, out bool enabled)
|
||||
&& enabled
|
||||
&& def.Matches(XivChatType.None, desc);
|
||||
}
|
||||
|
||||
// check for custom filters if enabled
|
||||
filter |= this.plugin.Config.CustomPFFilter && PartyFinder.MatchesCustomFilters(desc, this.plugin.Config);
|
||||
|
||||
|
@ -99,12 +95,12 @@ namespace NoSoliciting {
|
|||
|
||||
bool filter = false;
|
||||
|
||||
// check for RMT if enabled
|
||||
filter |= this.plugin.Config.FilterChat && this.plugin.Definitions.Chat.RMT.Matches(text);
|
||||
// check for RP ads if enabled
|
||||
filter |= this.plugin.Config.FilterChatRPAds && this.plugin.Definitions.Global.Roleplay.Matches(text);
|
||||
// check for FC recruitment if enabled
|
||||
filter |= this.plugin.Config.FilterFCRecruitments && this.plugin.Definitions.Chat.FreeCompany.Matches(text);
|
||||
foreach (Definition def in this.plugin.Definitions.Chat.Values) {
|
||||
filter |= this.plugin.Config.FilterStatus.TryGetValue(def.Id, out bool enabled)
|
||||
&& enabled
|
||||
&& def.Matches(type, text);
|
||||
}
|
||||
|
||||
// check for custom filters if enabled
|
||||
filter |= this.plugin.Config.CustomChatFilter && Chat.MatchesCustomFilters(text, this.plugin.Config);
|
||||
|
||||
|
|
|
@ -1,7 +1,61 @@
|
|||
version: 2
|
||||
# This file defines the filters that NoSoliciting will use for
|
||||
# built-in filters.
|
||||
|
||||
# The version should be incremented for each commit including changes
|
||||
# to this file.
|
||||
|
||||
# There are three main sections: chat, party_finder, and global. The
|
||||
# chat and party_finder sections are for their respective areas (the
|
||||
# chat log and the Party Finder window), and the global section
|
||||
# applies to both.
|
||||
|
||||
# Each subsection is a separate built-in filter that can be toggled on
|
||||
# and off. The option shown in the UI is defined in the
|
||||
# subsection. For global subsections, {} can be inserted into the
|
||||
# option name to substitute either "chat" or "Party Finder" as
|
||||
# appropriate.
|
||||
|
||||
# Subsections can have ignore_case (defaults to false) and normalise
|
||||
# (defaults to true) set. ignore_case will ignore casing for matching
|
||||
# against the matchers, and normalise will normalise text prior to
|
||||
# matching. Text normalisation consists of turning FFXIV-specific
|
||||
# unicode symbols into normal ASCII characters and running a NFKD
|
||||
# unicode decomposition on the result.
|
||||
|
||||
# Subsections also may filter based on channels with the channels key.
|
||||
# A list of channels may be specified, and the message will be ignored
|
||||
# if not in one of the specified channels. For the Party Finder, the
|
||||
# channel is always None. An empty list (or missing channels key) will
|
||||
# ignore the channel.
|
||||
|
||||
# Each subsection may specify whether it is enabled by default with the
|
||||
# default key. This should be used sparingly. This defaults to false.
|
||||
|
||||
# The real meat of the file is the matchers. There are two types of
|
||||
# matchers: required and likely. Both types have categories of strings
|
||||
# or regular expressions that should match. For required matchers, at
|
||||
# least one string or regex should match in *all* categories. For
|
||||
# likely matchers, at least one string or regex should match in the
|
||||
# value of likelihood_threshold (or greater) categories.
|
||||
|
||||
# If both required and likely matchers are specified, they both must
|
||||
# match. This means that all the categories of the required matchers
|
||||
# must find a match, *and* that at least likelihood_threshold matchers
|
||||
# must find a match in likely_matchers.
|
||||
|
||||
# Substring matchers are faster than regular expressions and are
|
||||
# specified just by using a string. Regular expression matchers are
|
||||
# slower but more flexible, and they are specified by using a regex
|
||||
# key, as can be seen below.
|
||||
|
||||
version: 3
|
||||
|
||||
chat:
|
||||
rmt:
|
||||
option:
|
||||
basic: Filter RMT from chat
|
||||
advanced: Enable built-in chat RMT filter
|
||||
default: true
|
||||
required_matchers:
|
||||
- - "4KGOLD"
|
||||
- "We have sufficient stock"
|
||||
|
@ -33,7 +87,13 @@ chat:
|
|||
- "offers Fantasia"
|
||||
- "finalfantasyxiv.com-se.ru" # phishing
|
||||
free_company:
|
||||
option:
|
||||
basic: Filter FC recruitments from chat
|
||||
advanced: Enable built-in chat FC recruitment filter
|
||||
ignore_case: true
|
||||
channels:
|
||||
- shout
|
||||
- yell
|
||||
likelihood_threshold: 3
|
||||
likely_matchers:
|
||||
# mentions free company
|
||||
|
@ -60,7 +120,6 @@ chat:
|
|||
# has common keywords
|
||||
- - family
|
||||
- community
|
||||
- new
|
||||
- veteran
|
||||
- seasoned
|
||||
- help
|
||||
|
@ -68,6 +127,10 @@ chat:
|
|||
|
||||
party_finder:
|
||||
rmt:
|
||||
option:
|
||||
basic: Filter RMT from Party Finder
|
||||
advanced: Enable built-in Party Finder RMT filter
|
||||
default: true
|
||||
ignore_case: true
|
||||
required_matchers:
|
||||
# discord
|
||||
|
@ -88,6 +151,9 @@ party_finder:
|
|||
|
||||
global:
|
||||
roleplay:
|
||||
option:
|
||||
basic: 'Filter RP advertisements from {}'
|
||||
advanced: 'Enable built-in {} RP filter'
|
||||
ignore_case: true
|
||||
required_matchers:
|
||||
- - regex: 'w(ard)?\s*\d+[\s/,]*(p(lot)?|a(pt\.?|partment)?)\s*\d+'
|
||||
|
|
Loading…
Reference in New Issue
Block a user