tsunami

log in
history

ForumSearcher.cs

Luke Breuer
0001-01-01 05:00 UTC

using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace Time.Classes
{
    public class ForumSearcher
    {
        public string RegexSearch { protected set; get; }
        public string[] UsernameMatches { protected set; get; }
        public string[] QuotesUsernames { protected set; get; }
        public string[] QuotedByUsernames { protected set; get; }
        public bool SearchQuotes { protected set; get; }
        public string[] IgnoredBy { protected set; get; }
        public string InUrl { protected set; get; }
        public bool NumberedOutput { protected set; get; }

        public ForumSearcher(string search)
        {
            if (string.IsNullOrEmpty(search) || search.Trim().Length == 0)
                throw new ArgumentException("Must pass a non-empty string that consists of more than spaces.");

            Regex r = new Regex(@"\b(?<key>\w+):(?:(?<value>[^""' ]+)|""(?<value>[^""']+)"")");

            var ops = r
                .Matches(search)
                .Cast<Match>()
                .ToDictionary(m => m.Groups["key"].Value, m => m.Groups["value"].Value);

            Func<string, string> getAndRemove = key =>
                {
                    var value = ops[key];
                    ops.Remove(key);
                    return value;
                };

            Action<string, Action<string>> processKeyword = (keyword, action) =>
                {
                    if (ops.ContainsKey(keyword))
                        action(getAndRemove(keyword));
                };

            processKeyword("u", v => { UsernameMatches = v.Split(';', ','); });
            processKeyword("in", v =>
            {
                var inOpts = v.Split(' ');

                SearchQuotes = new[] { "q", "quote", "quotes" }.Intersect(inOpts).Any();
            });

            processKeyword("quotes", v => { QuotesUsernames = v.Split(';', ','); });
            processKeyword("quotedby", v => { QuotedByUsernames = v.Split(';', ','); });

            processKeyword("ignoredby", v =>
            {
                IgnoredBy = v.Split(';', ',');

                if (IgnoredBy.Length == 1 && IgnoredBy[0] == "*")
                    IgnoredBy = new string[0];
            });

            processKeyword("inurl", v => { InUrl = v; });
            processKeyword("output", v => { NumberedOutput = v.ToLower().Split(';', ',').Contains("numbers"); });

            //if (ops.ContainsKey("numbered")

            // MUST BE AT END
            string rSearch = Regex.Replace(r.Replace(search, ""), @"\s{2,}", " ").Trim();

            RegexSearch = string.IsNullOrEmpty(rSearch)
                ? null
                : "(?i)" + rSearch;
        }
    }
}