[smuxi/experiments/configurable_message_patterns: 1/6] Engine: implemented user configurable message patterns
- From: Mirco M. M. Bauer <mmmbauer src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [smuxi/experiments/configurable_message_patterns: 1/6] Engine: implemented user configurable message patterns
- Date: Sun, 16 Feb 2014 18:23:24 +0000 (UTC)
commit 25f55c051426c88ae9c999a544a4755fa27c5106
Author: Mirco Bauer <meebey meebey net>
Date: Sat Feb 15 14:32:01 2014 +0100
Engine: implemented user configurable message patterns
src/Engine-IRC/Protocols/Irc/IrcMessageBuilder.cs | 2 +-
src/Engine/Config/Config.cs | 16 ++
src/Engine/Config/MessageBuilderSettings.cs | 109 +++++++-------
src/Engine/Config/MessagePatternModel.cs | 134 +++++++++++++++++
src/Engine/Config/MessagePatternSettings.cs | 160 +++++++++++++++++++++
src/Engine/Engine.csproj | 2 +
src/Engine/Makefile.am | 2 +
src/Engine/Messages/MessageBuilder.cs | 92 +++++++------
src/Engine/Session.cs | 56 +++++---
9 files changed, 458 insertions(+), 115 deletions(-)
---
diff --git a/src/Engine-IRC/Protocols/Irc/IrcMessageBuilder.cs
b/src/Engine-IRC/Protocols/Irc/IrcMessageBuilder.cs
index 94deaa7..f4f7caf 100644
--- a/src/Engine-IRC/Protocols/Irc/IrcMessageBuilder.cs
+++ b/src/Engine-IRC/Protocols/Irc/IrcMessageBuilder.cs
@@ -209,7 +209,7 @@ namespace Smuxi.Engine
msgPart.Italic = italic;
msgPart.ForegroundColor = fg_color;
msgPart.BackgroundColor = bg_color;
- Append(ParseSmartLinks(msgPart));
+ Append(ParsePatterns(msgPart));
} while (controlCharFound);
return this;
}
diff --git a/src/Engine/Config/Config.cs b/src/Engine/Config/Config.cs
index 4ab2a86..051c806 100644
--- a/src/Engine/Config/Config.cs
+++ b/src/Engine/Config/Config.cs
@@ -618,6 +618,22 @@ namespace Smuxi.Engine
LoadUserEntry(user, cprefix + "MessageType", null);
LoadUserEntry(user, cprefix + "MessagePattern", null);
}
+
+ string lprefix = "MessagePatterns/";
+ var linkKeys = GetList(prefix + user + "/" + lprefix + "MessagePatterns");
+ if (linkKeys == null) {
+ linkKeys = new string[] {};
+ m_Preferences[prefix + user + "/" + lprefix + "MessagePatterns"] = new string[] {};
+ } else {
+ m_Preferences[prefix + user + "/" + lprefix + "MessagePatterns"] = linkKeys;
+ }
+ foreach (var linkKey in linkKeys) {
+ lprefix = "MessagePatterns/" + linkKey + "/";
+ LoadUserEntry(user, lprefix + "MessagePartPattern", String.Empty);
+ LoadUserEntry(user, lprefix + "MessagePartType", String.Empty);
+ LoadUserEntry(user, lprefix + "LinkFormat", String.Empty);
+ LoadUserEntry(user, lprefix + "TextFormat", String.Empty);
+ }
}
}
diff --git a/src/Engine/Config/MessageBuilderSettings.cs b/src/Engine/Config/MessageBuilderSettings.cs
index cf1da9c..0a41d13 100644
--- a/src/Engine/Config/MessageBuilderSettings.cs
+++ b/src/Engine/Config/MessageBuilderSettings.cs
@@ -20,46 +20,39 @@
using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;
+using Smuxi.Common;
namespace Smuxi.Engine
{
public class MessageBuilderSettings
{
- public class SmartLink
- {
- public Regex MessagePartPattern { get; set; }
- public Type MessagePartType { get; set; }
- // what is linked to
- public string LinkFormat { get; set; }
- // what is displayed
- public string TextFormat { get; set; }
-
- public SmartLink(Regex pattern)
- {
- if (pattern == null) {
- throw new ArgumentNullException("pattern");
- }
- MessagePartPattern = pattern;
- MessagePartType = typeof(UrlMessagePartModel);
- }
- }
-
- static List<SmartLink> BuiltinSmartLinks { get; set; }
- public List<SmartLink> SmartLinks { get; private set; }
+ static List<MessagePatternModel> BuiltinPatterns { get; set; }
+ static List<MessagePatternModel> GlobalPatterns { get; set; }
+ public List<MessagePatternModel> Patterns { get; private set; }
static MessageBuilderSettings()
{
- BuiltinSmartLinks = new List<SmartLink>();
+ BuiltinPatterns = new List<MessagePatternModel>();
InitBuiltinSmartLinks();
+ GlobalPatterns = new List<MessagePatternModel>();
}
public MessageBuilderSettings()
{
- // No need to lock BuiltinSmartLinks as List<T> is thread-safe for
+ var builtinPatterns = BuiltinPatterns;
+ var globalPatterns = GlobalPatterns;
+
+ // No need to lock BuiltinPatterns as List<T> is thread-safe for
// multiple readers as long as there is no writer at the same time.
// BuiltinSmartLinks is only written once before the first instance
// of MessageBuilderSettings is created via the static initializer.
- SmartLinks = new List<SmartLink>(BuiltinSmartLinks);
+ Patterns = new List<MessagePatternModel>(builtinPatterns.Count +
+ globalPatterns.Count);
+ Patterns.AddRange(builtinPatterns);
+
+ // GlobalPatterns is only set atomically in ApplyStaticConfig()
+ // and the collection is never modified after that
+ Patterns.AddRange(globalPatterns);
}
static void InitBuiltinSmartLinks()
@@ -86,7 +79,7 @@ namespace Smuxi.Engine
@"(<[1-9][0-9]* attachments?>)
(http://www\.facebook\.com/messages/\?action=read&tid=[0-9a-f]+)",
RegexOptions.Compiled
);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "{2}",
TextFormat = "{1}",
});
@@ -96,14 +89,14 @@ namespace Smuxi.Engine
protocol_user_domain_port_path,
RegexOptions.IgnoreCase | RegexOptions.Compiled
);
- BuiltinSmartLinks.Add(new SmartLink(regex));
+ BuiltinPatterns.Add(new MessagePatternModel(regex));
// email
regex = new Regex(
@"(?:mailto:)?(" + user_domain + ")",
RegexOptions.IgnoreCase | RegexOptions.Compiled
);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "mailto:{1}"
});
@@ -113,31 +106,31 @@ namespace Smuxi.Engine
string heuristic_domain = @"(?:(?:" + subdomain + ")+(?:" + common_tld + ")|localhost)";
string heuristic_address = heuristic_domain + "(?:" + path + ")?";
regex = new Regex(heuristic_address, RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://{0}"
});
// Smuxi bugtracker
regex = new Regex(@"smuxi#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://www.smuxi.org/issues/show/{1}"
});
// RFCs
regex = new Regex(@"RFC[ -]?([0-9]+) (?:s\.|ss\.|sec\.|sect\.|section) ?([1-9][0-9.]*)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://tools.ietf.org/html/rfc{1}#section-{2}"
});
regex = new Regex(@"RFC[ -]?([0-9]+) (?:p\.|pp\.|page) ?(" + short_number + ")",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://tools.ietf.org/html/rfc{1}#page-{2}"
});
regex = new Regex(@"RFC[ -]?([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://www.ietf.org/rfc/rfc{1}.txt"
});
@@ -147,147 +140,147 @@ namespace Smuxi.Engine
// boost bugtracker
regex = new Regex(@"boost#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "https://svn.boost.org/trac/boost/ticket/{1}"
});
// Claws bugtracker
regex = new Regex(@"claws#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://www.thewildbeast.co.uk/claws-mail/bugzilla/show_bug.cgi?id={1}"
});
// CVE list
regex = new Regex(@"CVE-[0-9]{4}-[0-9]{4,}",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://cve.mitre.org/cgi-bin/cvename.cgi?name={0}"
});
// CPAN bugtracker
regex = new Regex(@"RT#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://rt.cpan.org/Public/Bug/Display.html?id={1}"
});
// Debian bugtracker
regex = new Regex(@"deb#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://bugs.debian.org/{1}"
});
// Debian Security Advisories (DSA)
regex = new Regex(@"DSA-([0-9]{4})(-[0-9]{1,2})?",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://www.debian.org/security/dsa-{1}"
});
// openSUSE feature tracker
regex = new Regex(@"fate#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://features.opensuse.org/{1}"
});
// freedesktop bugtracker
regex = new Regex(@"fdo#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://bugs.freedesktop.org/{1}"
});
// GNU bugtracker
regex = new Regex(@"gnu#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://debbugs.gnu.org/{1}"
});
// GCC bugtracker
regex = new Regex(@"gcc#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://gcc.gnu.org/bugzilla/show_bug.cgi?id={1}"
});
// GNOME bugtracker
regex = new Regex(@"bgo#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://bugzilla.gnome.org/{1}"
});
// KDE bugtracker
regex = new Regex(@"kde#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://bugs.kde.org/{1}"
});
// kernel bugtracker
regex = new Regex(@"bko#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://bugzilla.kernel.org/show_bug.cgi?id={1}"
});
// launchpad bugtracker
regex = new Regex(@"LP#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://launchpad.net/bugs/{1}"
});
// Mozilla bugtracker
regex = new Regex(@"bmo#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://bugzilla.mozilla.org/{1}"
});
// Novell bugtracker
regex = new Regex(@"bnc#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://bugzilla.novell.com/{1}"
});
// Redhat bugtracker
regex = new Regex(@"rh#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://bugzilla.redhat.com/{1}"
});
// Samba bugtracker
regex = new Regex(@"bso#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://bugzilla.samba.org/show_bug.cgi?id={1}"
});
// sourceforge bugtracker
regex = new Regex(@"sf#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://sf.net/support/tracker.php?aid={1}"
});
// Xfce bugtracker
regex = new Regex(@"bxo#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://bugzilla.xfce.org/show_bug.cgi?id={1}"
});
// Xamarin bugtracker
regex = new Regex(@"bxc#([0-9]+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- BuiltinSmartLinks.Add(new SmartLink(regex) {
+ BuiltinPatterns.Add(new MessagePatternModel(regex) {
LinkFormat = "http://bugzilla.xamarin.com/show_bug.cgi?id={1}"
});
@@ -304,8 +297,16 @@ namespace Smuxi.Engine
// TODO: JID
}
- public void ApplyConfig(UserConfig userConfig)
+ public static void ApplyStaticConfig(UserConfig userConfig)
{
+ Trace.Call(userConfig);
+
+ if (userConfig == null) {
+ throw new ArgumentNullException("userConfig");
+ }
+
+ var settings = new MessagePatternSettings(userConfig);
+ GlobalPatterns = settings.GetList();
}
}
}
diff --git a/src/Engine/Config/MessagePatternModel.cs b/src/Engine/Config/MessagePatternModel.cs
new file mode 100644
index 0000000..b32ffe5
--- /dev/null
+++ b/src/Engine/Config/MessagePatternModel.cs
@@ -0,0 +1,134 @@
+// Smuxi - Smart MUltipleXed Irc
+//
+// Copyright (c) 2014 Mirco Bauer <meebey meebey net>
+//
+// Full GPL License: <http://www.gnu.org/licenses/gpl.txt>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+using System;
+using System.Text.RegularExpressions;
+
+namespace Smuxi.Engine
+{
+ public class MessagePatternModel
+ {
+ public int? ID { get; set; }
+ public Regex MessagePartPattern { get; set; }
+ public Type MessagePartType { get; set; }
+ // what is linked to
+ public string LinkFormat { get; set; }
+ // what is displayed
+ public string TextFormat { get; set; }
+
+ protected string ConfigKeyPrefix {
+ get {
+ if (ID == null) {
+ throw new ArgumentNullException("ID");
+ }
+ return "MessagePatterns/" + ID + "/";
+ }
+ }
+
+ public MessagePatternModel(Regex pattern)
+ {
+ if (pattern == null) {
+ throw new ArgumentNullException("pattern");
+ }
+ MessagePartPattern = pattern;
+ MessagePartType = typeof(UrlMessagePartModel);
+ }
+
+ public MessagePatternModel(int id)
+ {
+ ID = id;
+ }
+
+ public void Load(UserConfig config)
+ {
+ if (ID == null) {
+ throw new InvalidOperationException("ID must not be null.");
+ }
+
+ Load(config, ID.Value);
+ }
+
+ public virtual void Load(UserConfig config, int id)
+ {
+ if (config == null) {
+ throw new ArgumentNullException("config");
+ }
+
+ // don't use ConfigKeyPrefix, so exception guarantees can be kept
+ string prefix = "MessagePatterns/" + id + "/";
+ if (config[prefix + "MessagePartPattern"] == null) {
+ // SmartLink does not exist
+ throw new ArgumentException("MessagePattern ID not found in config", "id");
+ }
+
+ ID = id;
+ // now we have a valid ID, ConfigKeyPrefix works
+ var messagePartPattern = (string) config[ConfigKeyPrefix + "MessagePartPattern"];
+ if (messagePartPattern.StartsWith("/") && messagePartPattern.EndsWith("/i")) {
+ var regexPattern = messagePartPattern.Substring(1, messagePartPattern.Length - 3);
+ MessagePartPattern = new Regex(regexPattern, RegexOptions.IgnoreCase |
RegexOptions.Compiled);
+ } else {
+ MessagePartPattern = new Regex(messagePartPattern, RegexOptions.Compiled);
+ }
+ var messagePartType = (string) config[ConfigKeyPrefix + "MessagePartType"];
+ switch (messagePartType.ToLower()) {
+ case "url":
+ MessagePartType = typeof(UrlMessagePartModel);
+ break;
+ case "image":
+ MessagePartType = typeof(ImageMessagePartModel);
+ break;
+ }
+ LinkFormat = (string) config[ConfigKeyPrefix + "LinkFormat"];
+ TextFormat = (string) config[ConfigKeyPrefix + "TextFormat"];
+ }
+
+ public virtual void Save(UserConfig config)
+ {
+ if (config == null) {
+ throw new ArgumentNullException("config");
+ }
+
+ if (MessagePartPattern == null) {
+ config[ConfigKeyPrefix + "MessagePartPattern"] = String.Empty;
+ } else {
+ config[ConfigKeyPrefix + "MessagePartPattern"] = MessagePartPattern.ToString();
+ }
+ if (MessagePartType == typeof(ImageMessagePartModel)) {
+ config[ConfigKeyPrefix + "MessagePartType"] = "Image";
+ } else if (MessagePartType == typeof(UrlMessagePartModel)) {
+ config[ConfigKeyPrefix + "MessagePartType"] = "Url";
+ } else {
+ config[ConfigKeyPrefix + "MessagePartType"] = String.Empty;
+ }
+ config[ConfigKeyPrefix + "LinkFormat"] = LinkFormat ?? String.Empty;
+ config[ConfigKeyPrefix + "TextFormat"] = TextFormat ?? String.Empty;
+ }
+
+ public override string ToString()
+ {
+ return String.Format("<{0}>", ToTraceString());
+ }
+
+ public string ToTraceString()
+ {
+ return String.Format("{0}", ID);
+ }
+ }
+}
diff --git a/src/Engine/Config/MessagePatternSettings.cs b/src/Engine/Config/MessagePatternSettings.cs
new file mode 100644
index 0000000..fc55e03
--- /dev/null
+++ b/src/Engine/Config/MessagePatternSettings.cs
@@ -0,0 +1,160 @@
+/*
+ * Smuxi - Smart MUltipleXed Irc
+ *
+ * Copyright (c) 2014 Mirco Bauer <meebey meebey net>
+ *
+ * Full GPL License: <http://www.gnu.org/licenses/gpl.txt>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+using System;
+using System.Collections.Generic;
+using Smuxi.Common;
+using Smuxi.Engine;
+
+namespace Smuxi.Engine
+{
+ public class MessagePatternSettings
+ {
+ UserConfig UserConfig { get; set; }
+
+ protected string[] PatternIDs {
+ get {
+ return (string[]) UserConfig["MessagePatterns/MessagePatterns"];
+ }
+ set {
+ UserConfig["MessagePatterns/MessagePatterns"] = value;
+ }
+ }
+
+ public MessagePatternSettings(UserConfig userConfig)
+ {
+ if (userConfig == null) {
+ throw new ArgumentNullException("userConfig");
+ }
+
+ UserConfig = userConfig;
+ }
+
+ public List<MessagePatternModel> GetList()
+ {
+ var keys = PatternIDs;
+ var list = new List<MessagePatternModel>(keys.Length);
+ if (keys == null) {
+ return list;
+ }
+ foreach (var key in keys) {
+ int parsedKey = Int32.Parse(key);
+ var link = Get(parsedKey);
+ if (link == null) {
+ continue;
+ }
+ list.Add(link);
+ }
+ return list;
+ }
+
+ public MessagePatternModel Get(int id)
+ {
+ Trace.Call(id);
+
+ string prefix = "MessagePatterns/" + id + "/";
+ if (UserConfig[prefix + "MessagePartPattern"] == null) {
+ // link does not exist
+ return null;
+ }
+ var link = new MessagePatternModel(id);
+ link.Load(UserConfig);
+ return link;
+ }
+
+ public int Add(MessagePatternModel link)
+ {
+ return Add(link, -1);
+ }
+
+ public int Add(MessagePatternModel link, int id)
+ {
+ Trace.Call(link, id);
+
+ if (link == null) {
+ throw new ArgumentNullException("link");
+ }
+
+ string[] keys = PatternIDs;
+ if (keys == null) {
+ keys = new string[] {};
+ }
+ int highestKey = 0;
+ int newKey = id;
+ if (id == -1) {
+ foreach (string key in keys) {
+ int parsedKey = Int32.Parse(key);
+ if (parsedKey > highestKey) {
+ highestKey = parsedKey;
+ }
+ }
+ newKey = ++highestKey;
+ }
+
+ link.ID = newKey;
+ link.Save(UserConfig);
+
+ var keyList = new List<string>(keys);
+ keyList.Add(link.ID.ToString());
+ PatternIDs = keyList.ToArray();
+ return newKey;
+ }
+
+ public void Set(MessagePatternModel link)
+ {
+ Trace.Call(link);
+
+ if (link == null) {
+ throw new ArgumentNullException("link");
+ }
+
+ link.Save(UserConfig);
+ }
+
+ public void Remove(int key)
+ {
+ Trace.Call(key);
+
+ string section = "MessagePatterns/" + key + "/";
+ string[] keys = PatternIDs;
+ if (keys == null) {
+ keys = new string[] {};
+ }
+ var keyList = new List<string>(keys);
+ int idx = keyList.IndexOf(key.ToString());
+ if (idx == -1) {
+ // key not found
+ return;
+ }
+ keyList.RemoveAt(idx);
+ UserConfig.Remove(section);
+ PatternIDs = keyList.ToArray();
+ }
+
+ public void Save()
+ {
+ Trace.Call();
+
+ UserConfig.Save();
+ }
+ }
+}
diff --git a/src/Engine/Engine.csproj b/src/Engine/Engine.csproj
index 8bd8d98..37a6091 100644
--- a/src/Engine/Engine.csproj
+++ b/src/Engine/Engine.csproj
@@ -107,6 +107,8 @@
<Compile Include="Hooks\Environments\CommandHookEnvironment.cs" />
<Compile Include="Config\MessageBuilderSettings.cs" />
<Compile Include="Hooks\Environments\PersonHookEnvironment.cs" />
+ <Compile Include="Config\MessagePatternModel.cs" />
+ <Compile Include="Config\MessagePatternSettings.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Protocols\" />
diff --git a/src/Engine/Makefile.am b/src/Engine/Makefile.am
index 1403715..99b0152 100644
--- a/src/Engine/Makefile.am
+++ b/src/Engine/Makefile.am
@@ -94,6 +94,8 @@ FILES = \
Config/ProxyType.cs \
Config/EntrySettings.cs \
Config/MessageBuilderSettings.cs \
+ Config/MessagePatternModel.cs \
+ Config/MessagePatternSettings.cs \
Protocols/ProtocolManagerBase.cs \
Protocols/ProtocolManagerFactory.cs \
Protocols/ProtocolManagerInfoModel.cs \
diff --git a/src/Engine/Messages/MessageBuilder.cs b/src/Engine/Messages/MessageBuilder.cs
index 49bce15..a944ecc 100644
--- a/src/Engine/Messages/MessageBuilder.cs
+++ b/src/Engine/Messages/MessageBuilder.cs
@@ -275,7 +275,7 @@ namespace Smuxi.Engine
public virtual MessageBuilder AppendMessage(string msg)
{
- return Append(ParseSmartLinks(CreateText(msg)));
+ return Append(ParsePatterns(CreateText(msg)));
}
public MessageBuilder AppendMessage(ContactModel sender, string msg)
@@ -856,82 +856,90 @@ namespace Smuxi.Engine
return LibraryCatalog.GetString(msg, LibraryTextDomain);
}
- public static IList<MessagePartModel> ParseSmartLinks(TextMessagePartModel textPart,
- List<MessageBuilderSettings.SmartLink> links)
+ public static IList<MessagePartModel> ParsePatterns(TextMessagePartModel textPart,
+ List<MessagePatternModel> patterns)
{
+ if (textPart == null) {
+ throw new ArgumentNullException("textPart");
+ }
+ if (patterns == null) {
+ throw new ArgumentNullException("patterns");
+ }
+
var msgParts = new List<MessagePartModel>();
- if (links.Count == 0) {
- // all smartlinks have been tried -> this text is PURE text
+ if (patterns.Count == 0) {
+ // all patterns have been tried -> this text is PURE text
msgParts.Add(textPart);
return msgParts;
}
- var subLinks = new List<MessageBuilderSettings.SmartLink>(links);
- var link = subLinks.First();
- subLinks.Remove(link);
+
+ var remainingPatterns = new List<MessagePatternModel>(patterns);
+ var pattern = remainingPatterns.First();
+ remainingPatterns.Remove(pattern);
- var linkMatch = link.MessagePartPattern.Match(textPart.Text);
- if (!linkMatch.Success) {
- // no smartlinks in this MessagePart, try other smartlinks
- return ParseSmartLinks(textPart, subLinks);
+ var match = pattern.MessagePartPattern.Match(textPart.Text);
+ if (!match.Success) {
+ // no matches in this MessagePart, try other smartlinks
+ return ParsePatterns(textPart, remainingPatterns);
}
int lastindex = 0;
do {
- var groupValues = new string[linkMatch.Groups.Count];
+ var groupValues = new string[match.Groups.Count];
int i = 0;
- foreach (Group @group in linkMatch.Groups) {
+ foreach (Group @group in match.Groups) {
groupValues[i++] = @group.Value;
}
string url;
- if (String.IsNullOrEmpty(link.LinkFormat)) {
- url = linkMatch.Value;
+ if (String.IsNullOrEmpty(pattern.LinkFormat)) {
+ url = match.Value;
} else {
- url = String.Format(link.LinkFormat, groupValues);
+ url = String.Format(pattern.LinkFormat, groupValues);
}
string text;
- if (String.IsNullOrEmpty(link.TextFormat)) {
- text = linkMatch.Value;
+ if (String.IsNullOrEmpty(pattern.TextFormat)) {
+ text = match.Value;
} else {
- text = String.Format(link.TextFormat, groupValues);
+ text = String.Format(pattern.TextFormat, groupValues);
}
- if (lastindex != linkMatch.Index) {
- // there were some non-url-chars before this url
- // copy TextMessagePartModel
- var notLinkPart = new TextMessagePartModel(textPart);
+ if (lastindex != match.Index) {
+ // there were some non-matching-chars before the match
+ // copy that to a TextMessagePartModel
+ var notMatchPart = new TextMessagePartModel(textPart);
// only take the proper chunk of text
- notLinkPart.Text = textPart.Text.Substring(lastindex, linkMatch.Index - lastindex);
- // and try other smartlinks on this part
- var parts = ParseSmartLinks(notLinkPart, subLinks);
+ notMatchPart.Text = textPart.Text.Substring(lastindex, match.Index - lastindex);
+ // and try other patterns on this part
+ var parts = ParsePatterns(notMatchPart, remainingPatterns);
foreach (var part in parts) {
msgParts.Add(part);
}
}
- MessagePartModel model;
- if (link.MessagePartType == typeof(UrlMessagePartModel)) {
+ MessagePartModel msgPart;
+ if (pattern.MessagePartType == typeof(UrlMessagePartModel)) {
// no need to set URL and text if they are the same
text = text == url ? null : text;
- model = new UrlMessagePartModel(url, text);
- } else if (link.MessagePartType == typeof(ImageMessagePartModel)) {
- model = new ImageMessagePartModel(url, text);
+ msgPart = new UrlMessagePartModel(url, text);
+ } else if (pattern.MessagePartType == typeof(ImageMessagePartModel)) {
+ msgPart = new ImageMessagePartModel(url, text);
} else {
- model = new TextMessagePartModel(text);
+ msgPart = new TextMessagePartModel(text);
}
- msgParts.Add(model);
- lastindex = linkMatch.Index + linkMatch.Length;
- linkMatch = linkMatch.NextMatch();
- } while (linkMatch.Success);
+ msgParts.Add(msgPart);
+ lastindex = match.Index + match.Length;
+ match = match.NextMatch();
+ } while (match.Success);
if (lastindex != textPart.Text.Length) {
// there were some non-url-chars before this url
// copy TextMessagePartModel
- TextMessagePartModel notLinkPart = new TextMessagePartModel(textPart);
+ var notMatchPart = new TextMessagePartModel(textPart);
// only take the proper chunk of text
- notLinkPart.Text = textPart.Text.Substring(lastindex);
+ notMatchPart.Text = textPart.Text.Substring(lastindex);
// and try other smartlinks on this part
- var parts = ParseSmartLinks(notLinkPart, subLinks);
+ var parts = ParsePatterns(notMatchPart, remainingPatterns);
foreach (var part in parts) {
msgParts.Add(part);
}
@@ -939,9 +947,9 @@ namespace Smuxi.Engine
return msgParts;
}
- public IEnumerable<MessagePartModel> ParseSmartLinks(TextMessagePartModel part)
+ public IEnumerable<MessagePartModel> ParsePatterns(TextMessagePartModel part)
{
- return ParseSmartLinks(part, Settings.SmartLinks);
+ return ParsePatterns(part, Settings.Patterns);
}
}
}
diff --git a/src/Engine/Session.cs b/src/Engine/Session.cs
index 7bebecd..80bcf13 100644
--- a/src/Engine/Session.cs
+++ b/src/Engine/Session.cs
@@ -154,6 +154,7 @@ namespace Smuxi.Engine
_UserConfig.Changed += OnUserConfigChanged;
_FilterListController = new FilterListController(_UserConfig);
_Filters = _FilterListController.GetFilterList().Values;
+ MessageBuilderSettings.ApplyStaticConfig(_UserConfig);
_Chats = new List<ChatModel>();
InitSessionChat();
@@ -730,31 +731,50 @@ namespace Smuxi.Engine
return;
}
string setKey = setParam.Split('=')[0];
- string setValue = setParam.Split('=')[1];
+ string setValue = String.Join(
+ "=", setParam.Split('=').Skip(1).ToArray()
+ );
object oldValue = _UserConfig[setKey];
+ if (oldValue == null && setKey.StartsWith("MessagePatterns/")) {
+ var id = setKey.Split('/')[1];
+ var parsedId = Int32.Parse(id);
+ var msgPatternSettings = new MessagePatternSettings(_UserConfig);
+ var pattern = msgPatternSettings.Get(parsedId);
+ if (pattern == null) {
+ // pattern does not exist, create it with default values
+ pattern = new MessagePatternModel(parsedId);
+ msgPatternSettings.Add(pattern, parsedId);
+ oldValue = _UserConfig[setKey];
+ }
+ }
if (oldValue == null) {
builder.AppendErrorText(
_("Invalid config key: '{0}'"),
setKey
);
- } else {
- try {
- object newValue = Convert.ChangeType(setValue, oldValue.GetType());
- _UserConfig[setKey] = newValue;
- builder.AppendText("{0} = {1}", setKey, newValue.ToString());
- } catch (InvalidCastException) {
- builder.AppendErrorText(
- _("Could not convert config value: '{0}' to type: {1}"),
- setValue,
- oldValue.GetType().Name
- );
- } catch (FormatException) {
- builder.AppendErrorText(
- _("Could not convert config value: '{0}' to type: {1}"),
- setValue,
- oldValue.GetType().Name
- );
+ AddMessageToFrontend(cd, builder.ToMessage());
+ return;
+ }
+
+ try {
+ object newValue = Convert.ChangeType(setValue, oldValue.GetType());
+ _UserConfig[setKey] = newValue;
+ builder.AppendText("{0} = {1}", setKey, newValue.ToString());
+ if (setKey.StartsWith("MessagePatterns/")) {
+ MessageBuilderSettings.ApplyStaticConfig(UserConfig);
}
+ } catch (InvalidCastException) {
+ builder.AppendErrorText(
+ _("Could not convert config value: '{0}' to type: {1}"),
+ setValue,
+ oldValue.GetType().Name
+ );
+ } catch (FormatException) {
+ builder.AppendErrorText(
+ _("Could not convert config value: '{0}' to type: {1}"),
+ setValue,
+ oldValue.GetType().Name
+ );
}
break;
default:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]