public override string Evaluate(RequestProcess process) { try { if (process.Bot.SraixServices.TryGetValue(this.ServiceName, out var service)) { var text = this.Children?.Evaluate(process) ?? ""; process.Log(LogLevel.Diagnostic, "In element <sraix>: querying service '" + this.ServiceName + "' to process text '" + text + "'."); text = service.Process(text, this.Attributes, process); process.Log(LogLevel.Diagnostic, "In element <sraix>: the request returned '" + text + "'."); return(text); } else { process.User.Predicates["SraixException"] = nameof(KeyNotFoundException); process.User.Predicates["SraixExceptionMessage"] = "No service named '" + this.ServiceName + "' is known."; process.Log(LogLevel.Warning, "In element <sraix>: no service named '" + this.ServiceName + "' is known."); return((this.DefaultReply ?? new TemplateElementCollection(new Srai(new TemplateElementCollection("SRAIXFAILED")))).Evaluate(process)); } } catch (Exception ex) { process.User.Predicates["SraixException"] = ex.GetType().Name; process.User.Predicates["SraixExceptionMessage"] = ex.Message; process.Log(LogLevel.Warning, "In element <sraix>: service '" + this.ServiceName + "' threw " + ex.GetType().Name + ":\n" + ex.ToString()); return((this.DefaultReply ?? new TemplateElementCollection(new Srai(new TemplateElementCollection("SRAIXFAILED")))).Evaluate(process)); } }
public override string Evaluate(RequestProcess process) { process.Log(LogLevel.Info, $"In element <test>: running test {this.Name}"); string text = this.Children?.Evaluate(process) ?? ""; process.Log(LogLevel.Diagnostic, "In element <test>: processing text '" + text + "'."); var newRequest = new Aiml.Request(text, process.User, process.Bot); text = process.Bot.ProcessRequest(newRequest, false, false, process.RecursionDepth + 1, out var duration).ToString().Trim(); process.Log(LogLevel.Diagnostic, "In element <test>: the request returned '" + text + "'."); if (process.testResults != null) { var expectedResponse = this.ExpectedResponse.Evaluate(process).Trim(); TestResult result; if (process.Bot.Config.CaseSensitiveStringComparer.Equals(text, expectedResponse)) { result = TestResult.Pass(duration); } else { result = TestResult.Failure($"Expected response: {expectedResponse}\nActual response: {text}", duration); } process.testResults[this.Name] = result; } else { process.Log(LogLevel.Warning, "In element <test>: Tests are not being used."); } return(text); }
public override string Evaluate(RequestProcess process) { // Does the triple already exist? var clause = new Clause(this.Subject, this.Predicate, this.Object, true); clause.Evaluate(process); if (string.IsNullOrWhiteSpace(clause.subj) || string.IsNullOrWhiteSpace(clause.pred) || string.IsNullOrWhiteSpace(clause.obj)) { process.Log(LogLevel.Diagnostic, $"In element <addtriple>: Could not add triple with missing elements. Subject: {clause.subj} Predicate: {clause.pred} Object: {clause.obj}"); return(process.Bot.Config.DefaultTriple); } var triples = process.Bot.Triples.Match(clause); if (triples.Count != 0) { process.Log(LogLevel.Diagnostic, $"In element <addtriple>: Triple already exists at key {triples.First()}. Subject: {clause.subj} Predicate: {clause.pred} Object: {clause.obj}"); return(triples.First().ToString()); } // Add the triple. int key = process.Bot.Triples.Add(clause.subj, clause.pred, clause.obj); process.Log(LogLevel.Diagnostic, $"In element <addtriple>: Added a new triple with key {key}. Subject: {clause.subj} Predicate: {clause.pred} Object: {clause.obj}"); return(key.ToString()); }
public override string Evaluate(RequestProcess process) { var clause = new Clause(this.Subject, this.Predicate, this.Object, true); clause.Evaluate(process); if (string.IsNullOrWhiteSpace(clause.subj) || string.IsNullOrWhiteSpace(clause.pred) || string.IsNullOrWhiteSpace(clause.obj)) { process.Log(LogLevel.Diagnostic, $"In element <deletetriple>: Could not delete triple with missing elements. Subject: {clause.subj} Predicate: {clause.pred} Object: {clause.obj}"); return(process.Bot.Config.DefaultTriple); } var triples = process.Bot.Triples.Match(clause); if (triples.Count == 0) { process.Log(LogLevel.Diagnostic, $"In element <deletetriple>: No such triple exists. Subject: {clause.subj} Predicate: {clause.pred} Object: {clause.obj}"); return(process.Bot.Config.DefaultTriple); } var index = triples.Single(); process.Bot.Triples.Remove(index); process.Log(LogLevel.Diagnostic, $"In element <deletetriple>: Deleted the triple with key {index}. Subject: {clause.subj} Predicate: {clause.pred} Object: {clause.obj}"); return(index.ToString()); }
public override string Evaluate(RequestProcess process) { string text = process.star[0]; process.Log(LogLevel.Diagnostic, "In element <sr>: processing text '" + text + "'."); var newRequest = new Aiml.Request(text, process.User, process.Bot); text = process.Bot.ProcessRequest(newRequest, false, false, process.RecursionDepth + 1, out _).ToString(); process.Log(LogLevel.Diagnostic, "In element <sr>: the request returned '" + text + "'."); return(text); }
public override string Evaluate(RequestProcess process) { // Evaluate the contents of clauses. foreach (var clause in this.Clauses) { clause.Evaluate(process); } string[] visibleVars; if (this.Variables == null) { visibleVars = new string[0]; } else { visibleVars = this.Variables.Evaluate(process).Split((char[])null, StringSplitOptions.RemoveEmptyEntries); } // Start with an empty tuple. Tuple tuple = new Tuple(new HashSet <string>(visibleVars, process.Bot.Config.StringComparer)); var tuples = this.SelectFromRemainingClauses(process, tuple, 0); process.Log(LogLevel.Diagnostic, $"In element <select>: Found {tuples.Count} matching {(tuples.Count == 1 ? "tuple" : "tuples")}."); if (tuples.Count == 0) { return(process.Bot.Config.DefaultTriple); } return(string.Join(" ", tuples.Select(t => t.Index))); }
public override string Evaluate(RequestProcess process) { StringBuilder builder = new StringBuilder(); li item; int loops = 0; do { ++loops; if (loops > process.Bot.Config.LoopLimit) { process.Log(LogLevel.Warning, "Loop limit exceeded. User: "******"; path: \"" + process.Path + "\""); throw new LoopLimitException(); } item = this.Pick(process); if (item == null) { return(string.Empty); } builder.Append(item.Children?.Evaluate(process)); } while (item.Children != null && item.Children.Loop); return(builder.ToString()); }
public Template?Search(RequestSentence sentence, RequestProcess process, string that, bool traceSearch) { if (process.RecursionDepth > sentence.Bot.Config.RecursionLimit) { sentence.Bot.Log(LogLevel.Warning, "Recursion limit exceeded. User: "******"; raw input: \"" + sentence.Request.Text + "\""); throw new RecursionLimitException(); } // Generate the input path. var messageSplit = sentence.Text.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries); var thatSplit = that.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries); var topicSplit = sentence.Bot.Normalize(sentence.User.Topic).Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries); var inputPath = new string[messageSplit.Length + thatSplit.Length + topicSplit.Length + 2]; int i = 0; messageSplit.CopyTo(inputPath, 0); i += messageSplit.Length; inputPath[i++] = "<that>"; thatSplit.CopyTo(inputPath, i); i += thatSplit.Length; inputPath[i++] = "<topic>"; topicSplit.CopyTo(inputPath, i); if (traceSearch) { process.Log(LogLevel.Diagnostic, "Normalized path: " + string.Join(" ", inputPath)); } var result = this.Search(sentence, process, inputPath, 0, traceSearch, MatchState.Message); return(result); }
public override string Evaluate(RequestProcess process) { string command = this.Command.Evaluate(process); Process process2 = new Process(); if (Environment.OSVersion.Platform < PlatformID.Unix) { // Windows process2.StartInfo = new ProcessStartInfo(Path.Combine(Environment.SystemDirectory, "cmd.exe"), "/Q /D /C \"" + Regex.Replace(command, @"[/\\:*?""<>^]", "^$0") + "\""); // /C string Carries out the command specified by string and then terminates. // /Q Turns echo off. // /D Disable execution of AutoRun commands from registry (see 'CMD /?'). } else if (Environment.OSVersion.Platform == PlatformID.Unix) { // UNIX process2.StartInfo = new ProcessStartInfo(Path.Combine(Path.GetPathRoot(Environment.SystemDirectory), "bin", "sh"), command.Replace(@"\", @"\\").Replace("\"", "\\\"")); } process2.StartInfo.UseShellExecute = false; process2.StartInfo.RedirectStandardOutput = true; process2.StartInfo.RedirectStandardError = true; process.Log(LogLevel.Diagnostic, $"In element <system>: executing {process2.StartInfo.FileName} {process2.StartInfo.Arguments}"); process2.Start(); string output = process2.StandardOutput.ReadToEnd(); string output2 = process2.StandardError.ReadToEnd(); process2.WaitForExit((int)process.Bot.Config.Timeout); if (!process2.HasExited) { process.Log(LogLevel.Diagnostic, $"In element <system>: the process timed out."); } else if (process2.ExitCode != 0) { process.Log(LogLevel.Diagnostic, $"In element <system>: the process exited with code {process2.ExitCode}."); } return(output); }
internal void WriteGossip(RequestProcess process, string message) { var e = new GossipEventArgs(message); this.OnGossip(e); if (e.Handled) { return; } process.Log(LogLevel.Gossip, "Gossip from " + process.User.ID + ": " + message); }
public override string Evaluate(RequestProcess process) { string key = this.Key.Evaluate(process); string value = (this.Children?.Evaluate(process) ?? "").Trim(); var dictionary = this.LocalVar ? process.Variables : process.User.Predicates; if (process.Bot.Config.UnbindPredicatesWithDefaultValue && value == (this.LocalVar ? process.Bot.Config.DefaultPredicate : process.Bot.Config.GetDefaultPredicate(key))) { dictionary.Remove(key); process.Log(LogLevel.Diagnostic, "In element <set>: Unbound " + (this.LocalVar ? "local variable" : "predicate") + " '" + key + "' with default value '" + value + "'."); } else { dictionary[key] = value; process.Log(LogLevel.Diagnostic, "In element <set>: Set " + (this.LocalVar ? "local variable" : "predicate") + " '" + key + "' to '" + value + "'."); } return(value); }
public override string Evaluate(RequestProcess process) { this.Clause.Evaluate(process); // Find triples that match. var triples = process.Bot.Triples.Match(this.Clause); if (triples.Count == 0) { process.Log(LogLevel.Diagnostic, $"In element <uniq>: No matching triple exists. Subject: {this.Clause.subj} Predicate: {this.Clause.pred} Object: {this.Clause.obj}"); return(process.Bot.Config.DefaultTriple); } else if (triples.Count > 1) { process.Log(LogLevel.Diagnostic, $"In element <uniq>: Found {triples.Count} matching triples. Subject: {this.Clause.subj} Predicate: {this.Clause.pred} Object: {this.Clause.obj}"); } var tripleIndex = triples.First(); var triple = process.Bot.Triples[tripleIndex]; process.Log(LogLevel.Diagnostic, $"In element <uniq>: Found triple {tripleIndex}. Subject: {triple.Subject} Predicate: {triple.Predicate} Object: {triple.Object}"); // Get the result. if (this.Clause.obj.StartsWith("?")) { return(triple.Object); } if (this.Clause.pred.StartsWith("?")) { return(triple.Predicate); } if (this.Clause.subj.StartsWith("?")) { return(triple.Subject); } process.Log(LogLevel.Warning, $"In element <uniq>: The clause contains no variables. Subject: {this.Clause.subj} Predicate: {this.Clause.pred} Object: {this.Clause.obj}"); return(process.Bot.Config.DefaultTriple); }
public override string Evaluate(RequestProcess process) { // Evaluate <eval> tags. XmlNode node = this.Node.Clone(); this.ProcessXml(node, process); // Learn the result. process.Log(LogLevel.Diagnostic, $"In element <learn>: learning new category for {process.User.ID}: {node.OuterXml}"); AimlLoader loader = new AimlLoader(process.Bot); loader.ProcessCategory(process.User.Graphmaster, node, null); return(string.Empty); }
public override string Evaluate(RequestProcess process) { // Evaluate <eval> tags. XmlNode node = this.Node.Clone(); this.ProcessXml(node, process); // Learn the result. process.Log(LogLevel.Diagnostic, "In element <learnf>: learning new category: " + node.OuterXml); AimlLoader loader = new AimlLoader(process.Bot); loader.ProcessCategory(process.Bot.Graphmaster, node, null); // Write it to a file. bool newFile = !File.Exists(process.Bot.Config.LearnfFile) || new FileInfo(process.Bot.Config.LearnfFile).Length < 7; StreamWriter writer = new StreamWriter(File.Open("learnf.aiml", FileMode.OpenOrCreate, FileAccess.Write)); if (newFile) { writer.WriteLine("<!-- This file contains AIML categories the bot has learned via <learnf> elements. -->"); writer.WriteLine(); writer.WriteLine("<aiml version=\"2.0\">"); writer.WriteLine(); } else { // Seek to just before the closing </aiml> tag. writer.BaseStream.Seek(-7, SeekOrigin.End); } writer.WriteLine("<!-- Learned from " + process.User.ID + " via category '" + process.Path + "' on " + DateTime.Now + ". -->"); writer.Write(node.InnerXml.Trim('\r', '\n')); writer.WriteLine(); writer.WriteLine(); writer.Write("</aiml>"); writer.Close(); return(string.Empty); }
public li?Pick(RequestProcess process) { string value; foreach (var item in this.items) { string?key = item.Key?.Evaluate(process); string?checkValue = item.Value?.Evaluate(process); Dictionary <string, string> dictionary; if (item.LocalVar) { dictionary = process.Variables; } else { dictionary = process.User.Predicates; } if (key != null && checkValue != null) { if (checkValue == "*") { // '*' is a match if the predicate is bound at all. if (item.LocalVar) { if (process.Variables.TryGetValue(key, out value)) { process.Log(LogLevel.Diagnostic, $"In element <condition>: Local variable {key} matches *."); return(item); } } else { if (process.User.Predicates.TryGetValue(key, out value)) { process.Log(LogLevel.Diagnostic, $"In element <condition>: Local variable {key} matches *."); return(item); } } } else { if (item.LocalVar) { if (process.Bot.Config.StringComparer.Equals(process.GetVariable(key), checkValue)) { process.Log(LogLevel.Diagnostic, $"In element <condition>: Local variable {key} matches {checkValue}."); return(item); } } else { if (process.Bot.Config.StringComparer.Equals(checkValue, process.User.GetPredicate(key))) { process.Log(LogLevel.Diagnostic, $"In element <condition>: {(item.LocalVar ? "Local variable" : "Predicate")} {key} matches {checkValue}."); return(item); } } } // No match; keep looking. process.Log(LogLevel.Diagnostic, $"In element <condition>: {(item.LocalVar ? "Local variable" : "Predicate")} {key} does not match {checkValue}."); } else if (key == null && checkValue == null) { // Default case. return(item); } else { process.Log(LogLevel.Warning, "In element <condition>: Missing name, var or value attribute in <li>."); } } return(null); }
public override string Evaluate(RequestProcess process) { string format = null; if (this.Format != null) { format = this.Format.Evaluate(process); } string jformat = null; if (this.JFormat != null) { jformat = this.JFormat.Evaluate(process); } string localeString = null; if (this.Locale != null) { localeString = this.Locale.Evaluate(process); } string timezone = null; if (this.Timezone != null) { timezone = this.Timezone.Evaluate(process); } CultureInfo locale; if (localeString == null) { locale = process.Bot.Config.Locale; } else { try { locale = CultureInfo.CreateSpecificCulture(localeString.Replace('_', '-')); } catch (CultureNotFoundException) { process.Log(LogLevel.Warning, "In element <date>: Locale '" + localeString + "' is unknown."); locale = process.Bot.Config.Locale; } } var date = DateTime.Now; TimeSpan offset; if (timezone != null && TimeSpan.TryParse(timezone, out offset)) { offset = -offset; } else { offset = TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow); } if (format != null) { if (jformat != null) { process.Log(LogLevel.Warning, "In element <date>: format and jformat are both specified. format will be used."); } return(DateUnixFormat(new DateTimeOffset(date, offset), format, locale)); } if (jformat != null) { return(DateJavaFormat(new DateTimeOffset(date, offset), jformat, locale)); } return(date.Date.ToString(locale)); }
internal Response ProcessRequest(Request request, bool trace, bool useTests, int recursionDepth, out TimeSpan duration) { var stopwatch = Stopwatch.StartNew(); var that = this.Normalize(request.User.GetThat()); // Respond to each sentence separately. var builder = new StringBuilder(); foreach (var sentence in request.Sentences) { var process = new RequestProcess(sentence, recursionDepth, useTests); process.Log(LogLevel.Diagnostic, "Normalized text: " + sentence.Text); string output; try { var template = request.User.Graphmaster.Search(sentence, process, that, trace); if (template != null) { process.template = template; process.Log(LogLevel.Diagnostic, "Input matched user-specific category '" + process.Path + "'."); } else { template = this.Graphmaster.Search(sentence, process, that, trace); if (template != null) { process.template = template; process.Log(LogLevel.Diagnostic, "Input matched category '" + process.Path + "' in file '" + Path.GetFileName(template.FileName) + "'."); } } if (template != null) { output = template.Content.Evaluate(process); } else { process.Log(LogLevel.Warning, "No match for input '" + sentence.Text + "'."); output = this.Config.DefaultResponse; } } catch (TimeoutException) { output = this.Config.TimeoutMessage; } catch (RecursionLimitException) { output = this.Config.RecursionLimitMessage; } catch (LoopLimitException) { output = this.Config.LoopLimitMessage; } output = output.Trim(); if (output.Length > 0) { if (builder.Length != 0) { builder.Append(' '); } builder.Append(output); } process.Finish(); } var response = new Response(request, builder.ToString()); request.Response = response; stopwatch.Stop(); duration = stopwatch.Elapsed; return(response); }
public override string Evaluate(RequestProcess process) { string jformat = null; string format = null; if (this.JFormat != null) { jformat = this.JFormat.Evaluate(process); } DateTime start; DateTime end; string startString, endString; // Parse the dates. startString = this.Start.Evaluate(process); try { if (jformat == null) { start = DateTime.Parse(startString); } else { format = ConvertJavaFormat(jformat); start = DateTime.ParseExact(startString, jformat, CultureInfo.CurrentCulture, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal); } } catch (FormatException) { if (format == null) { process.Log(LogLevel.Warning, "In element <interval>: Could not parse '" + startString + "' as a date."); } else { process.Log(LogLevel.Warning, "In element <interval>: Could not parse '" + startString + "' as a date with format '" + jformat + "'."); } return("unknown"); } endString = this.End.Evaluate(process); try { if (jformat == null) { end = DateTime.Parse(endString); } else { format = ConvertJavaFormat(jformat); end = DateTime.ParseExact(endString, jformat, CultureInfo.CurrentCulture, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal); } } catch (FormatException) { if (format == null) { process.Log(LogLevel.Warning, "In element <interval>: Could not parse '" + endString + "' as a date."); } else { process.Log(LogLevel.Warning, "In element <interval>: Could not parse '" + endString + "' as a date with format '" + jformat + "'."); } return("unknown"); } // Output the result. string unit = this.Style.Evaluate(process); switch (unit) { case "milliseconds": return(((int)(end - start).TotalMilliseconds).ToString()); case "seconds": return(((int)(end - start).TotalSeconds).ToString()); case "minutes": return(((int)(end - start).TotalMinutes).ToString()); case "hours": return(((int)(end - start).TotalHours).ToString()); case "days": return(((int)(end - start).TotalDays).ToString()); case "weeks": return((((int)(end - start).TotalDays) / 7).ToString()); case "months": int interval = (end.Year - start.Year) * 12 + end.Month - start.Month; if (end - new DateTime(end.Year, end.Month, 1, 0, 0, 0, end.Kind) < start - new DateTime(start.Year, start.Month, 1, 0, 0, 0, start.Kind)) { // end falls earlier in the month than start. --interval; } return(interval.ToString()); case "years": interval = end.Year - start.Year; if (end - new DateTime(end.Year, 1, 1, 0, 0, 0, end.Kind) < start - new DateTime(start.Year, 1, 1, 0, 0, 0, start.Kind)) { // end falls earlier in the year than start. --interval; } return(interval.ToString()); default: process.Log(LogLevel.Warning, "In element <interval>: The style parameter evaluated to an invalid unit: " + unit); return("unknown"); } }