diff --git a/bot/bot.sln b/bot/bot.sln
index 1851e8c..a422777 100644
--- a/bot/bot.sln
+++ b/bot/bot.sln
@@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bot", "bot\bot.csproj", "{1E318685-BF0A-4508-AE47-76C7442994D7}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "responses", "responses\responses.csproj", "{5CC66C93-279D-4E00-9FE1-FAFF54FC4D6F}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -13,6 +15,10 @@ Global
{1E318685-BF0A-4508-AE47-76C7442994D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E318685-BF0A-4508-AE47-76C7442994D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E318685-BF0A-4508-AE47-76C7442994D7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5CC66C93-279D-4E00-9FE1-FAFF54FC4D6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5CC66C93-279D-4E00-9FE1-FAFF54FC4D6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5CC66C93-279D-4E00-9FE1-FAFF54FC4D6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5CC66C93-279D-4E00-9FE1-FAFF54FC4D6F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/bot/bot/Autonomous.cs b/bot/bot/Autonomous.cs
index 893a1ba..0ac97de 100644
--- a/bot/bot/Autonomous.cs
+++ b/bot/bot/Autonomous.cs
@@ -3,9 +3,126 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Reflection;
+using MySql.Data.MySqlClient;
namespace bot {
class Autonomous {
-
+ public int id;
+ public string name;
+ public int startDay;
+ public int[] startTime;
+ public int periodicity;
+ public int randomness;
+ public Type responseType;
+ public string parameters;
+
+ public DateTime nextTrigger = new DateTime(0);
+ public DateTime linkTrigger = new DateTime(0);
+
+ public int autolinkid;
+ public Autonomous autolink;
+ public bool linkrespond;
+ public int timeout;
+ public int torandomness;
+
+ public Random rng = new Random();
+
+ public Autonomous(int id, string name, int startDay, int[] startTime, int periodicity, int randomness,
+ string responseType, string parameters,
+ int autolinkid, bool linkrespond, int timeout, int torandomness) {
+ this.id = id;
+ this.name = name;
+ this.startDay = startDay;
+ this.startTime = startTime;
+ this.periodicity = periodicity;
+ this.randomness = randomness;
+
+ this.responseType = Assembly.GetExecutingAssembly().GetTypes().Where(t => String.Equals(t.Namespace, "bot.responses", StringComparison.Ordinal) && String.Equals(t.Name, responseType, StringComparison.Ordinal)).ToArray()[0];
+ this.parameters = parameters;
+
+ this.autolinkid = autolinkid;
+ this.linkrespond = linkrespond;
+ this.timeout = timeout;
+ this.torandomness = torandomness;
+
+ CalculateNextTrigger();
+ }
+
+ public Autonomous(int id, string name, int startDay, int[] startTime, int periodicity, int randomness,
+ int responseId, string parameters,
+ int autolinkid, bool linkrespond, int timeout, int torandomness) {
+ this.id = id;
+ this.name = name;
+ this.startDay = startDay;
+ this.startTime = startTime;
+ this.periodicity = periodicity;
+ this.randomness = randomness;
+
+ string responseType = (string)(new MySqlCommand("SELECT `name` FROM `resptypes` WHERE `id`=" + responseId, _G.conn)).ExecuteScalar();
+ this.responseType = Assembly.GetExecutingAssembly().GetTypes().Where(t => String.Equals(t.Namespace, "bot.responses", StringComparison.Ordinal) && String.Equals(t.Name, responseType, StringComparison.Ordinal)).ToArray()[0];
+ this.parameters = parameters;
+
+ this.autolinkid = autolinkid;
+ this.linkrespond = linkrespond;
+ this.timeout = timeout;
+ this.torandomness = torandomness;
+
+ CalculateNextTrigger();
+ }
+
+ public void triggerRoutine(bool force = false) {
+ if(_G.getLocalTimeFromUTC() > nextTrigger || force) {
+ ResponseCaller.callResponse(responseType, parameters, new Message("null","null"));
+ CalculateNextTrigger();
+ if(autolinkid != -1) {
+ linkTrigger = _G.getLocalTimeFromUTC().AddSeconds(timeout + (rng.Next(2) == 0 ? 1 : -1) * rng.Next(torandomness));
+ Bot.ignoreResponses = linkrespond;
+ }
+ } else if(_G.getLocalTimeFromUTC() > linkTrigger && linkTrigger != new DateTime(0)) {
+ autolink.triggerRoutine(true);
+ linkTrigger = new DateTime(0);
+ Bot.ignoreResponses = false;
+ }
+ }
+
+ public void CalculateNextTrigger() {
+ DateTime now = _G.getLocalTimeFromUTC();
+
+ if(nextTrigger == new DateTime(0)) {
+ if(startDay == -2)
+ nextTrigger = now.AddSeconds(periodicity + (rng.Next(2) == 0 ? 1 : -1) * rng.Next(randomness));
+ else if(startDay == -1) {
+ if(startTime[0] == -1)
+ nextTrigger = now;
+ else {
+ if(now.Hour < startTime[0] || (now.Hour == startTime[0] && now.Minute < startTime[1]))
+ nextTrigger = new DateTime(now.Year, now.Month, now.Day, startTime[0], startTime[1], 0);
+ else {
+ DateTime tomorrow = now.AddDays(1);
+ nextTrigger = new DateTime(tomorrow.Year, tomorrow.Month, tomorrow.Day, startTime[0], startTime[1], 0);
+ }
+ }
+ } else if(startDay == -999)
+ nextTrigger = now.AddYears(1000);
+ else {
+ DateTime tmp;
+ if((int)now.DayOfWeek == startDay - 1) {
+ if(now.Hour < startTime[0] || (now.Hour == startTime[0] && now.Minute < startTime[1]))
+ nextTrigger = new DateTime(now.Year, now.Month, now.Day, startTime[0], startTime[1], 0);
+ else {
+ tmp = now.AddDays(7);
+ nextTrigger = new DateTime(tmp.Year, tmp.Month, tmp.Day, startTime[0], startTime[1], 0);
+ }
+ } else {
+ int adder = (startDay - 1) - (int)now.DayOfWeek;
+ tmp = now.AddDays(adder);
+ if(adder < 0) tmp.AddDays(7);
+ nextTrigger = new DateTime(tmp.Year, tmp.Month, tmp.Day, startTime[0], startTime[1], 0);
+ }
+ }
+ } else if(startDay != -999)
+ nextTrigger = now.AddSeconds(periodicity + (rng.Next(2) == 0 ? 1 : -1) * rng.Next(randomness));
+ }
}
}
diff --git a/bot/bot/Bot.cs b/bot/bot/Bot.cs
index 52bfb99..89a5103 100644
--- a/bot/bot/Bot.cs
+++ b/bot/bot/Bot.cs
@@ -19,6 +19,20 @@ namespace bot {
static List indResponseList = new List();
static List autoList = new List();
+ public static bool ignoreResponses = false;
+
+ public static void AutonomousThread() {
+ while(true) {
+ try {
+ foreach(Autonomous auto in autoList) {
+ auto.triggerRoutine();
+ }
+ } catch(Exception e) {
+ // catch this at some point
+ }
+ }
+ }
+
public static void loadNavigationList() {
List tmpList = new List();
var tmp = _G.spawnNewConnection();
@@ -61,7 +75,39 @@ namespace bot {
}
public static void loadAutonomousList() {
+ List tmpList = new List();
+ var tmp = _G.spawnNewConnection();
+ var r = Query.Reader("SELECT * FROM `autonomous`", tmp);
+ while(r.Read()) {
+ tmpList.Add(new Autonomous(
+ r.GetInt32("id"),
+ r.GetString("name"),
+ r.GetInt32("startday"),
+ new int[] { Int32.Parse(r.GetString("starttime").Split(',')[0]), Int32.Parse(r.GetString("starttime").Split(',')[1]) },
+ r.GetInt32("periodicity"),
+ r.GetInt32("randomness"),
+ r.GetInt32("respid"),
+ r.GetString("parameters"),
+ r.GetInt32("autolink"),
+ !r.GetBoolean("linkrespond"),
+ r.GetInt32("timeout"),
+ r.GetInt32("torandomness")));
+ }
+ r.Close();
+ tmp.Close();
+ autoList = tmpList;
+ // TODO improve this later
+ foreach(Autonomous auto in autoList) {
+ if(auto.autolinkid != -1) {
+ foreach(Autonomous autoauto in autoList) {
+ if(auto.autolinkid == autoauto.id) {
+ auto.autolink = autoauto;
+ break;
+ }
+ }
+ }
+ }
}
static void Main(string[] args) {
@@ -82,6 +128,10 @@ namespace bot {
loadResponseList();
Console.WriteLine("OK");
+ Console.Write("Loading autonomous routine list ...");
+ loadAutonomousList();
+ Console.WriteLine("OK");
+
Console.Write("Updating response types on database ... ");
tmp = "DELETE FROM resptypes WHERE ";
foreach(Type t in ResponseCaller.getResponseTypes()) {
@@ -136,35 +186,39 @@ namespace bot {
_G.startThread(Pulse.pulseThread);
- // TODO add autonomous thread start
-
Chat.reloadContext(_G.driver);
+ (new Thread(new ThreadStart(Bot.AutonomousThread))).Start();
+
Console.WriteLine(_G.propername + " has started successfully.");
DateTime lastAction = new DateTime(0);
while(Chat.isChatting(_G.driver)) {
Message msg = Chat.waitForNewMessage(_G.driver);
- if(msg == null) break;
- if(msg.msg == "!dump") {
- foreach(Response r in responseList)
- Chat.sendMessage("IF "+ r.condstr +" THEN "+ r.responseType.Name);
- }
- if(msg.msg == "!update") {
- Bot.loadResponseList();
- Chat.sendMessage("response list updated");
- }
+ if(!ignoreResponses) {
+ if(msg == null) break;
+ if(msg.msg == "!dump") {
+ foreach(Response r in responseList)
+ Chat.sendMessage("IF " + r.condstr + " THEN " + r.responseType.Name);
+ }
+ if(msg.msg == "!update") {
+ Bot.loadResponseList();
+ Chat.sendMessage("response list updated");
+ Bot.loadAutonomousList();
+ Chat.sendMessage("autonomous list updated");
+ }
- foreach(Response response in indResponseList) {
- if(response.triggerResponse(msg)) break;
- }
+ foreach(Response response in indResponseList) {
+ if(response.triggerResponse(msg)) break;
+ }
- foreach(Response response in responseList) {
- if((DateTime.Now - lastAction).TotalSeconds >= _G.defaultCooldown) {
- if(response.triggerResponse(msg)) {
- lastAction = DateTime.Now;
- break;
+ foreach(Response response in responseList) {
+ if((DateTime.Now - lastAction).TotalSeconds >= _G.defaultCooldown) {
+ if(response.triggerResponse(msg)) {
+ lastAction = DateTime.Now;
+ break;
+ }
}
}
}
diff --git a/bot/bot/Chat.cs b/bot/bot/Chat.cs
index 1fe364b..4091144 100644
--- a/bot/bot/Chat.cs
+++ b/bot/bot/Chat.cs
@@ -17,6 +17,8 @@ namespace bot {
static int currentMessage;
public static void reloadContext(FirefoxDriver d) {
+ while(!ProtectionContext.Protect()) ;
+
Console.WriteLine("reloading context");
while(true) {
try {
@@ -35,19 +37,26 @@ namespace bot {
Console.WriteLine("reloading context complete");
if(d.FindElement(By.Id("audioButton")).GetAttribute("class").ToLower() == "button")
d.FindElement(By.Id("audioButton")).Click();
+
+ ProtectionContext.Free();
}
- public static void sendMessage(string text) {
- sendMessage(text, _G.driver);
+ public static void sendMessage(string text, bool protect = true) {
+ sendMessage(text, _G.driver, protect);
}
- public static void sendMessage(string text, FirefoxDriver d) {
- // TODO protection context corrections
+ public static void sendMessage(string text, FirefoxDriver d, bool protect = true) {
+ if(protect)
+ while(!ProtectionContext.Protect()) ;
+
if(isChatting(d)) {
d.FindElement(By.Id("inputField")).SendKeys(text);
d.FindElement(By.Id("submitButton")).Click();
try { Thread.Sleep(500); } catch(Exception e) { }
}
+
+ if(protect)
+ ProtectionContext.Free();
}
public static bool isChatting(FirefoxDriver d) {
diff --git a/bot/bot/ProtectionContext.cs b/bot/bot/ProtectionContext.cs
new file mode 100644
index 0000000..aec82d7
--- /dev/null
+++ b/bot/bot/ProtectionContext.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bot {
+ class ProtectionContext {
+ private static bool isWriteable = true;
+ private static DateTime timeOfWriteProtection = new DateTime(0);
+ private static int maxProtectionTime = 45;
+
+ public static bool Protect() {
+ if(isWriteable == true || (DateTime.Now-timeOfWriteProtection).TotalSeconds > maxProtectionTime) {
+ isWriteable = false;
+ timeOfWriteProtection = DateTime.Now;
+ return true;
+ } else return false;
+ }
+
+ public static void Free() {
+ isWriteable = true;
+ }
+ }
+}
diff --git a/bot/bot/bot.csproj b/bot/bot/bot.csproj
index 23edd6c..919c403 100644
--- a/bot/bot/bot.csproj
+++ b/bot/bot/bot.csproj
@@ -87,6 +87,7 @@
+
diff --git a/bot/bot/conditions/msgcntword.cs b/bot/bot/conditions/msgcntword.cs
index abc4eec..ce4a194 100644
--- a/bot/bot/conditions/msgcntword.cs
+++ b/bot/bot/conditions/msgcntword.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace bot.conditions {
@@ -11,7 +12,8 @@ namespace bot.conditions {
}
static public bool performCheck(Message msg, string parameter) {
- return false; // implement
+ Regex matcher = new Regex("\\b"+ parameter.ToLower() +"\\b");
+ return matcher.IsMatch(msg.msg.ToLower());
}
}
}
diff --git a/bot/responses/Class1.cs b/bot/responses/Class1.cs
new file mode 100644
index 0000000..24961f0
--- /dev/null
+++ b/bot/responses/Class1.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace responses
+{
+ public class Class1
+ {
+ }
+}
diff --git a/bot/responses/Properties/AssemblyInfo.cs b/bot/responses/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ec4914f
--- /dev/null
+++ b/bot/responses/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("responses")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Hewlett-Packard")]
+[assembly: AssemblyProduct("responses")]
+[assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("dd73d63c-48bf-4a83-a3db-8f13dc5d70ad")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/bot/responses/responses.csproj b/bot/responses/responses.csproj
new file mode 100644
index 0000000..c05dbb2
--- /dev/null
+++ b/bot/responses/responses.csproj
@@ -0,0 +1,53 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {5CC66C93-279D-4E00-9FE1-FAFF54FC4D6F}
+ Library
+ Properties
+ responses
+ responses
+ v4.5
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/www/auto.php b/www/auto.php
index 0123b46..894ae63 100644
--- a/www/auto.php
+++ b/www/auto.php
@@ -6,17 +6,18 @@ if($_GET['del']) {
}
if($_POST["editId"]) {
- // TODO update this
- mysql_query("UPDATE `autonomous` SET `conditions`='". mysql_real_escape_string($c) ."', `respid`=". $_POST['resptype'] .", `parameters`='". mysql_real_escape_string($_POST['parameters']) ."', `cooldown`=". (($_POST['cdd']==0)?-1:$_POST['cooldown']) ." WHERE `id`=". $_POST['editId']) or die(mysql_error());
+ $stime = ($_POST['starttimehour'] == -1 || $_POST['starttimemin'] == -1 || $_POST['startday'] == -2) ? "-1,-1" : $_POST['starttimehour'] .",". $_POST['starttimemin'];
+ mysql_query("UPDATE `autonomous` SET `name`='". mysql_real_escape_string($_POST['arname']) ."', `startday`=". $_POST['startday'] .", `starttime`='". $stime ."', `periodicity`=". $_POST['period'] .", `randomness`=". $_POST['randomness'] .", `respid`=". $_POST['resptype'] .", `parameters`='". mysql_real_escape_string($_POST['parameters']) ."', `autolink`=". $_POST['autolink'] .", `linkrespond`=". (($_POST["respond"]?"1":"0")) .", `timeout`=". $_POST['timeout'] .", `torandomness`=". $_POST['torandom'] ." WHERE `id`=". $_POST['editId']) or die(mysql_error());
mysql_query("UPDATE `updater` SET `autonomous`=1 WHERE `id`=1");
header("Location: auto.php");
}
if($_POST["resptype"] && !$_POST["editId"]) {
+ $stime = ($_POST['starttimehour'] == -1 || $_POST['starttimemin'] == -1 || $_POST['startday'] == -2) ? "-1,-1" : $_POST['starttimehour'] .",". $_POST['starttimemin'];
if($_POST["autolink"] == -1)
- mysql_query("INSERT INTO `autonomous` (`conditions`,`respid`,`parameters`,`cooldown`) VALUES ('". mysql_real_escape_string($c) ."',". $_POST['resptype'] .",'". mysql_real_escape_string($_POST['parameters']) ."',". (($_POST['ccd']==0)?-1:$_POST['cooldown']) .")") or die(mysql_error());
+ mysql_query("INSERT INTO `autonomous` (`name`,`startday`,`starttime`,`periodicity`,`randomness`,`respid`,`parameters`) VALUES ('". mysql_real_escape_string($_POST['arname']) ."',". $_POST['startday'] .",'". $stime ."',". $_POST['period'] .",". $_POST['randomness'] .",". $_POST['resptype'] .",'". mysql_real_escape_string($_POST['parameters']) ."')") or die(mysql_error());
else
- // do query
+ mysql_query("INSERT INTO `autonomous` (`name`,`startday`,`starttime`,`periodicity`,`randomness`,`respid`,`parameters`,`autolink`,`linkrespond`,`timeout`,`torandomness`) VALUES ('". mysql_real_escape_string($_POST['arname']) ."',". $_POST['startday'] .",'". $stime ."',". $_POST['period'] .",". $_POST['randomness'] .",". $_POST['resptype'] .",'". mysql_real_escape_string($_POST['parameters']) ."',". $_POST['autolink'] .",". (($_POST["respond"]?"1":"0")) .",". $_POST['timeout'] .",". $_POST['torandom'] .")") or die(mysql_error());
mysql_query("UPDATE `updater` SET `autonomous`=1 WHERE `id`=1");
header("Location: auto.php");
}
@@ -27,7 +28,7 @@ include("header.php");
/*var defaultCool = cooldown; ?>;*/
function confirmDeletion(id) {
- var q = confirm("Are you sure you want to delete this response?");
+ var q = confirm("Are you sure you want to delete this autonomous routine?");
if(q) window.location.href = "auto.php?del="+id;
}
@@ -51,16 +52,18 @@ include("header.php");
function evaluateCondition() {
if(document.getElementById("arname").value.trim() != "") {
- if(doTimeTest("Periodicity",document.getElementById("period").value)) {
- if(doTimeTest("Randomness",document.getElementById("randomness").value)) {
- if(document.getElementById("autolink").selectedIndex != 0) {
- if(doTimeTest("Link timeout",document.getElementById("timeout").value)) {
- if(doTimeTest("Link randomness",document.getElementById("torandom").value)) {
- document.getElementById("auto").submit();
+ if(document.getElementById("startday").selectedIndex <= 2 || (document.getElementById("startday").selectedIndex > 2 && document.getElementById("sth").selectedIndex != 0 && document.getElementById("stm").selectedIndex != 0)) {
+ if(doTimeTest("Periodicity",document.getElementById("period").value)) {
+ if(doTimeTest("Randomness",document.getElementById("randomness").value,true)) {
+ if(document.getElementById("autolink").selectedIndex != 0) {
+ if(doTimeTest("Link timeout",document.getElementById("timeout").value)) {
+ if(doTimeTest("Link randomness",document.getElementById("torandom").value,true)) {
+ document.getElementById("auto").submit();
+ }
}
+ } else {
+ document.getElementById("auto").submit();
}
- } else {
- document.getElementById("auto").submit();
}
}
}
@@ -79,6 +82,13 @@ include("header.php");
}
}
+ function handleStartDayChange() {
+ if(document.getElementById("startday").selectedIndex > 1)
+ document.getElementById("stdisp").style.display = "inline";
+ else
+ document.getElementById("stdisp").style.display = "none";
+ }
+
/*function coolChange() {
if(document.getElementById("cdd").selectedIndex == 0) {
document.getElementById("cooldown").disabled = true;
@@ -94,22 +104,21 @@ include("header.php");
New Autonomous Routine
-
+
|
- ". parseConditionString($resp->conditions, mysql_fetch_object(mysql_query("SELECT * FROM `resptypes` WHERE `id`=". $resp->respid))->friendlyname) ."
+ ". $resp->name ."
|
";
- }*/
+ }
?>
@@ -120,8 +129,10 @@ include("header.php");
Trigger first routine on
-
After first trigger,
@@ -198,7 +211,7 @@ include("header.php");
id ."'>". $auto->name ."";
}
@@ -241,29 +254,76 @@ include("header.php");
-
-
-
|