diff --git a/RhinoReminds/ClientListener.cs b/RhinoReminds/ClientListener.cs
new file mode 100644
index 0000000..8094743
--- /dev/null
+++ b/RhinoReminds/ClientListener.cs
@@ -0,0 +1,108 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Recognizers.Text;
+using Microsoft.Recognizers.Text.DateTime;
+using Newtonsoft.Json;
+using S22.Xmpp;
+using S22.Xmpp.Client;
+using S22.Xmpp.Im;
+
+namespace RhinoReminds
+{
+	public class ClientListener
+	{
+		public readonly string Jid;
+		public string Username => Jid.Split('@')[0];
+		public string Hostname => Jid.Split('@')[1];
+		private readonly string password;
+
+		private ReminderList reminders = new ReminderList();
+
+		private XmppClient client;
+
+		public ClientListener(string inJid, string inPassword) {
+			Jid = inJid;
+			password = inPassword;
+		}
+
+		public async Task Start()
+		{
+			client = new XmppClient(Hostname, Username, password);
+			client.Error += errorHandler;
+			client.Message += messageHandler;
+			client.SubscriptionRequest += subscriptionRequestHandler;
+
+			// Connect to the server. This starts it's own thread that doesn't block the program exiting, apparently
+			client.Connect();
+
+			while (!client.Connected)
+				await Task.Delay(100);
+
+			Console.WriteLine($"[Rhino/Setup] Connected as {Jid}");
+
+			//client.SetStatus(Availability.Online);
+
+			await Task.Delay(Timeout.Infinite);
+		}
+
+		private bool subscriptionRequestHandler(Jid from) {
+			Console.WriteLine($"[Rhino/SubscriptionRequest] Approving subscription from {from}");
+			return true;
+		}
+
+		private void errorHandler(object sender, ErrorEventArgs e) {
+			Console.Error.WriteLine($"Error {e.Reason}: {e.Exception}");
+		}
+
+		private void messageHandler(object sender, MessageEventArgs eventArgs) {
+			Console.WriteLine($"[Rhino/Reciever] [Message] {eventArgs.Jid} | {eventArgs.Message.Body}");
+
+			string message = eventArgs.Message.Body;
+			string[] parts = Regex.Split(eventArgs.Message.Body.Trim(), @"\s+");
+			string instruction = parts[0].ToLower();
+
+			if (parts.Select((string nextPart) => nextPart.ToLower()).Contains("remind")) {
+				Console.WriteLine("[Rhino/Reciever] Identified remind request");
+
+				List<ModelResult> dateAiResult = DateTimeRecognizer.RecognizeDateTime(message, Culture.English);
+				if (dateAiResult.Count == 0) {
+					sendChatReply(eventArgs.Message, "Sorry, but I didn't recognise any date or time in that message.");
+					return;
+				}
+
+
+
+				//DateTime dateTime = dateAiResult[0].Resolution["values"]
+
+				sendChatReply(
+					eventArgs.Message,
+					"#1: " + (dateAiResult[0].Resolution["values"] as List<object>)[0].ToString() + "\n" + 
+					"JSON: " + JsonConvert.SerializeObject(
+						dateAiResult[0].Resolution["values"]
+					)
+				);
+			}
+		}
+
+		private void sendChatReply(Message originalMessage, string reply)
+		{
+			client.SendMessage(
+				originalMessage.From, reply,
+				null, originalMessage.Thread, MessageType.Chat
+			);
+		}
+
+		private bool isContact(Jid jid)
+		{
+			foreach (RosterItem nextContact in client.GetRoster()) {
+				if (nextContact.Jid == jid)
+					return true;
+			}
+			return false;
+		}
+	}
+}
diff --git a/RhinoReminds/Program.cs b/RhinoReminds/Program.cs
index f5341a1..9cf8156 100644
--- a/RhinoReminds/Program.cs
+++ b/RhinoReminds/Program.cs
@@ -8,8 +8,6 @@ namespace RhinoReminds
 	public class ProgramSettings
 	{
 		public string Jid = null;
-		public string Username => Jid.Split('@')[0];
-		public string Hostname => Jid.Split('@')[1];
 
 		public string Password = null;
 	}
@@ -54,19 +52,15 @@ namespace RhinoReminds
 			settings.Jid = Environment.GetEnvironmentVariable("XMPP_JID");
 			settings.Password = Environment.GetEnvironmentVariable("XMPP_PASSWORD");
 
+			Run();
+
 			return 0;
 		}
 
 		public static void Run()
 		{
-			XmppClient client = new XmppClient(
-				settings.Hostname,
-				settings.Username, settings.Password
-			);
-			client.Message += (object sender, MessageEventArgs e) => {
-				Console.WriteLine($"[Rhino/Reciever] {e.Jid} | {e.Message}");
-			};
-			client.Connect();
+			ClientListener client = new ClientListener(settings.Jid, settings.Password);
+			client.Start().Wait();
 		}
 	}
 }
diff --git a/RhinoReminds/Reminder.cs b/RhinoReminds/Reminder.cs
new file mode 100644
index 0000000..93504f1
--- /dev/null
+++ b/RhinoReminds/Reminder.cs
@@ -0,0 +1,18 @@
+﻿using System;
+namespace RhinoReminds
+{
+
+	public class Reminder
+	{
+		public int Id { get; }
+		public DateTime Time { get; }
+		public string Message { get; }
+
+		public Reminder(int inId, DateTime inTime, string inMessage)
+		{
+			Id = inId;
+			Time = inTime;
+			Message = inMessage;
+		}
+	}
+}
diff --git a/RhinoReminds/ReminderList.cs b/RhinoReminds/ReminderList.cs
new file mode 100644
index 0000000..17f534f
--- /dev/null
+++ b/RhinoReminds/ReminderList.cs
@@ -0,0 +1,26 @@
+﻿using System;
+using System.Collections.Generic;
+
+namespace RhinoReminds
+{
+	public delegate void OnReminderListUpdateHandler(object sender, Reminder newReminder);
+
+	public class ReminderList
+	{
+		private int nextId = 0;
+		public SortedList<DateTime, Reminder> Reminders = new SortedList<DateTime, Reminder>();
+
+		public event OnReminderListUpdateHandler OnReminderListUpdate;
+
+		public ReminderList() {
+
+		}
+
+		public Reminder CreateReminder(DateTime time, string message) {
+			Reminder result = new Reminder(nextId++, time, message);
+			Reminders.Add(time, result);
+			OnReminderListUpdate(this, result);
+			return result;
+		}
+	}
+}
diff --git a/RhinoReminds/RhinoReminds.csproj b/RhinoReminds/RhinoReminds.csproj
index 64437e4..716b444 100644
--- a/RhinoReminds/RhinoReminds.csproj
+++ b/RhinoReminds/RhinoReminds.csproj
@@ -33,10 +33,38 @@
     <Reference Include="S22.Xmpp">
       <HintPath>..\packages\S22.Xmpp.1.0.0.0\lib\net45\S22.Xmpp.dll</HintPath>
     </Reference>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Collections.Immutable">
+      <HintPath>..\packages\System.Collections.Immutable.1.4.0\lib\netstandard2.0\System.Collections.Immutable.dll</HintPath>
+    </Reference>
+    <Reference Include="System.ValueTuple">
+      <HintPath>..\packages\System.ValueTuple.4.4.0\lib\net47\System.ValueTuple.dll</HintPath>
+    </Reference>
+    <Reference Include="mscorlib" />
+    <Reference Include="Microsoft.Recognizers.Definitions">
+      <HintPath>..\packages\Microsoft.Recognizers.Text.1.1.2\lib\net462\Microsoft.Recognizers.Definitions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Recognizers.Text">
+      <HintPath>..\packages\Microsoft.Recognizers.Text.1.1.2\lib\net462\Microsoft.Recognizers.Text.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Recognizers.Text.Number">
+      <HintPath>..\packages\Microsoft.Recognizers.Text.Number.1.1.2\lib\net462\Microsoft.Recognizers.Text.Number.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Recognizers.Text.NumberWithUnit">
+      <HintPath>..\packages\Microsoft.Recognizers.Text.NumberWithUnit.1.1.2\lib\net462\Microsoft.Recognizers.Text.NumberWithUnit.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Recognizers.Text.DateTime">
+      <HintPath>..\packages\Microsoft.Recognizers.Text.DateTime.1.1.2\lib\net462\Microsoft.Recognizers.Text.DateTime.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="ClientListener.cs" />
+    <Compile Include="Reminder.cs" />
+    <Compile Include="ReminderList.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="packages.config" />
diff --git a/RhinoReminds/packages.config b/RhinoReminds/packages.config
index d5aa67d..ec7a2ae 100644
--- a/RhinoReminds/packages.config
+++ b/RhinoReminds/packages.config
@@ -1,4 +1,11 @@
 ﻿<?xml version="1.0" encoding="utf-8"?>
 <packages>
+  <package id="Microsoft.Recognizers.Text" version="1.1.2" targetFramework="net47" />
+  <package id="Microsoft.Recognizers.Text.DateTime" version="1.1.2" targetFramework="net47" />
+  <package id="Microsoft.Recognizers.Text.Number" version="1.1.2" targetFramework="net47" />
+  <package id="Microsoft.Recognizers.Text.NumberWithUnit" version="1.1.2" targetFramework="net47" />
+  <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net47" />
   <package id="S22.Xmpp" version="1.0.0.0" targetFramework="net47" />
+  <package id="System.Collections.Immutable" version="1.4.0" targetFramework="net47" />
+  <package id="System.ValueTuple" version="4.4.0" targetFramework="net47" />
 </packages>
\ No newline at end of file
