diff --git a/Examples/Robots/Client.cs b/Examples/Robots/Client.cs
new file mode 100644
index 0000000..ca8d069
--- /dev/null
+++ b/Examples/Robots/Client.cs
@@ -0,0 +1,7 @@
+namespace Robots
+{
+ public class Client
+ {
+
+ }
+}
diff --git a/Examples/Robots/Program.cs b/Examples/Robots/Program.cs
new file mode 100644
index 0000000..604e98b
--- /dev/null
+++ b/Examples/Robots/Program.cs
@@ -0,0 +1,6 @@
+namespace Robots
+{
+ public class Program
+ {
+ }
+}
diff --git a/Examples/Robots/Robots.csproj b/Examples/Robots/Robots.csproj
new file mode 100644
index 0000000..cbfa581
--- /dev/null
+++ b/Examples/Robots/Robots.csproj
@@ -0,0 +1,7 @@
+
+
+
+ net5.0
+
+
+
diff --git a/IRCRobots/Bot.cs b/IRCRobots/Bot.cs
new file mode 100644
index 0000000..3e272b8
--- /dev/null
+++ b/IRCRobots/Bot.cs
@@ -0,0 +1,32 @@
+using System.Threading.Tasks;
+
+namespace IRCRobots
+{
+ public class Bot : IBot
+ {
+ public IServer CreateServer(string name)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public async Task Disconnected(IServer server)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public async Task Disconnect(IServer server)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public async Task AddServer(string name, ConnectionParams connectionParams)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public async Task Run()
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+}
diff --git a/IRCRobots/Capability.cs b/IRCRobots/Capability.cs
new file mode 100644
index 0000000..dc9ba6c
--- /dev/null
+++ b/IRCRobots/Capability.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace IRCRobots
+{
+ public class Capability : ICapability
+ {
+ public string Name { get; set; }
+ public string DraftName { get; set; }
+ public string Alias { get; }
+ public IEnumerable DependsOn { get; set; }
+ private IEnumerable Caps { get; }
+
+ public Capability()
+ {
+ Alias ??= Name;
+ Caps = new List {Name, DraftName};
+ }
+
+ public string? Available(IEnumerable capabilities)
+ {
+ return Caps.FirstOrDefault(cap => cap != null && capabilities.Contains(cap));
+ }
+
+ public bool Match(string capability)
+ {
+ return Caps.Contains(capability);
+ }
+ }
+}
diff --git a/IRCRobots/ConnectionParams.cs b/IRCRobots/ConnectionParams.cs
new file mode 100644
index 0000000..ba1dc39
--- /dev/null
+++ b/IRCRobots/ConnectionParams.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+
+#nullable enable
+namespace IRCRobots
+{
+ public class ConnectionParams
+ {
+ public string Nickname { get; set; }
+ public string Host { get; set; }
+ public int Port { get; set; }
+ public bool UseTLS { get; set; }
+ public string? Username { get; set; } = null;
+ public string? Realname { get; set; } = null;
+ public string? Bindhost { get; set; } = null;
+ public string? Password { get; set; } = null;
+ public bool VerifyTLS { get; set; } = true;
+ public SASLParams? SASL { get; set; } = null;
+ public STSPolicy? STS { get; set; } = null;
+ public ResumePolicy? Resume { get; set; } = null;
+ public int Reconnect { get; set; } = 10; // seconds
+ public IEnumerable AltNicknames { get; set; } = new List();
+ public IEnumerable Autojoin { get; set; } = new List();
+ }
+}
diff --git a/IRCRobots/IBot.cs b/IRCRobots/IBot.cs
new file mode 100644
index 0000000..cb29856
--- /dev/null
+++ b/IRCRobots/IBot.cs
@@ -0,0 +1,13 @@
+using System.Threading.Tasks;
+
+namespace IRCRobots
+{
+ public interface IBot
+ {
+ public IServer CreateServer(string name);
+ public Task Disconnected(IServer server);
+ public Task Disconnect(IServer server);
+ public Task AddServer(string name, ConnectionParams connectionParams);
+ public Task Run();
+ }
+}
diff --git a/IRCRobots/ICapability.cs b/IRCRobots/ICapability.cs
new file mode 100644
index 0000000..e50d27e
--- /dev/null
+++ b/IRCRobots/ICapability.cs
@@ -0,0 +1,12 @@
+#nullable enable
+using System.Collections.Generic;
+
+namespace IRCRobots
+{
+ public interface ICapability
+ {
+ public string? Available(IEnumerable capabilities);
+ public bool Match(string capability);
+ public string Copy() => "ICapability";
+ }
+}
diff --git a/IRCRobots/IRCRobots.csproj b/IRCRobots/IRCRobots.csproj
new file mode 100644
index 0000000..817ae70
--- /dev/null
+++ b/IRCRobots/IRCRobots.csproj
@@ -0,0 +1,11 @@
+
+
+
+ net5.0
+
+
+
+
+
+
+
diff --git a/IRCRobots/IServer.cs b/IRCRobots/IServer.cs
new file mode 100644
index 0000000..96048e9
--- /dev/null
+++ b/IRCRobots/IServer.cs
@@ -0,0 +1,34 @@
+#nullable enable
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using IRCTokens;
+
+namespace IRCRobots
+{
+ public interface IServer
+ {
+ public IEnumerable SendRaw(string line, SendPriority sendPriority = SendPriority.Default);
+ public IEnumerable Send(Line line, SendPriority sendPriority = SendPriority.Default);
+ public void SetThrottle(int rate, float time);
+ public (string address, int port) ServerAddress();
+ public Task Connect(ITCPTransport transport, ConnectionParams connectionParams);
+ public Task Disconnect();
+ public void LinePreread(Line line);
+ public void LinePresend(Line line);
+ public Task LineRead(Line line);
+ public Task LineSend(Line line);
+ public Task STSPolicy(STSPolicy stsPolicy);
+ public Task ResumePolicy(ResumePolicy resumePolicy);
+ public bool CapAgreed(ICapability capability);
+ public string? CapAvailable(ICapability capability);
+ public Task SASLAuth(SASLParams saslParams);
+ }
+
+ public enum SendPriority
+ {
+ High = 0,
+ Medium = 10,
+ Low = 20,
+ Default = Medium
+ }
+}
diff --git a/IRCRobots/ITCPTransport.cs b/IRCRobots/ITCPTransport.cs
new file mode 100644
index 0000000..3e1590a
--- /dev/null
+++ b/IRCRobots/ITCPTransport.cs
@@ -0,0 +1,10 @@
+#nullable enable
+using System.Threading.Tasks;
+
+namespace IRCRobots
+{
+ public interface ITCPTransport
+ {
+ public Task Connect(string hostname, int port, bool useTLS, bool verifyTLS = true, string? bindhost = null);
+ }
+}
diff --git a/IRCRobots/MessageTag.cs b/IRCRobots/MessageTag.cs
new file mode 100644
index 0000000..71180ae
--- /dev/null
+++ b/IRCRobots/MessageTag.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace IRCRobots
+{
+ public class MessageTag
+ {
+ public MessageTag()
+ {
+ Tags = new[] {Name, DraftName};
+ }
+
+ public string Name { get; set; }
+ public string DraftName { get; set; }
+ public IEnumerable Tags { get; }
+
+ public string? Available(IEnumerable tags)
+ {
+ return Tags.FirstOrDefault(tag => tag != null && tags.Contains(tag));
+ }
+
+ public string? Get(Dictionary tags)
+ {
+ return "";
+ }
+ }
+}
diff --git a/IRCRobots/ResumePolicy.cs b/IRCRobots/ResumePolicy.cs
new file mode 100644
index 0000000..f16e899
--- /dev/null
+++ b/IRCRobots/ResumePolicy.cs
@@ -0,0 +1,8 @@
+namespace IRCRobots
+{
+ public class ResumePolicy
+ {
+ public string Address { get; set; }
+ public string Token { get; set; }
+ }
+}
diff --git a/IRCRobots/SASLParams.cs b/IRCRobots/SASLParams.cs
new file mode 100644
index 0000000..26f4bcf
--- /dev/null
+++ b/IRCRobots/SASLParams.cs
@@ -0,0 +1,7 @@
+namespace IRCRobots
+{
+ public class SASLParams
+ {
+ public string Mechanism { get; set; }
+ }
+}
diff --git a/IRCRobots/STSPolicy.cs b/IRCRobots/STSPolicy.cs
new file mode 100644
index 0000000..39b530f
--- /dev/null
+++ b/IRCRobots/STSPolicy.cs
@@ -0,0 +1,10 @@
+namespace IRCRobots
+{
+ public class STSPolicy
+ {
+ public int Created { get; set; }
+ public int Port { get; set; }
+ public int Duration { get; set; }
+ public bool Preload { get; set; }
+ }
+}
diff --git a/IRCRobots/SentLine.cs b/IRCRobots/SentLine.cs
new file mode 100644
index 0000000..52f6abb
--- /dev/null
+++ b/IRCRobots/SentLine.cs
@@ -0,0 +1,11 @@
+using IRCTokens;
+
+namespace IRCRobots
+{
+ public class SentLine
+ {
+ public int Id { get; set; }
+ public SendPriority Priority { get; set; }
+ public Line Line { get; set; }
+ }
+}
diff --git a/IRCRobots/Server.cs b/IRCRobots/Server.cs
new file mode 100644
index 0000000..34a93e9
--- /dev/null
+++ b/IRCRobots/Server.cs
@@ -0,0 +1,90 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using IRCStates;
+using IRCTokens;
+
+namespace IRCRobots
+{
+ public class Server : IServer
+ {
+ private int SentCount { get; set; }
+
+ public IEnumerable SendRaw(string line, SendPriority sendPriority = SendPriority.Default)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public IEnumerable Send(Line line, SendPriority sendPriority = SendPriority.Default)
+ {
+ LinePresend(line);
+ var sentLine = new SentLine {Id = SentCount, Priority = sendPriority, Line = line};
+ SentCount++;
+ return new[] {sentLine};
+ }
+
+ public void SetThrottle(int rate, float time)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public (string address, int port) ServerAddress()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public async Task Connect(ITCPTransport transport, ConnectionParams connectionParams)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public async Task Disconnect()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public void LinePreread(Line line)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public void LinePresend(Line line)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public async Task LineRead(Line line)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public async Task LineSend(Line line)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public async Task STSPolicy(STSPolicy stsPolicy)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public async Task ResumePolicy(ResumePolicy resumePolicy)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public bool CapAgreed(ICapability capability)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public string? CapAvailable(ICapability capability)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public async Task SASLAuth(SASLParams saslParams)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+}
diff --git a/IRCSharp.Tests/Robots/Glob.cs b/IRCSharp.Tests/Robots/Glob.cs
new file mode 100644
index 0000000..26a71af
--- /dev/null
+++ b/IRCSharp.Tests/Robots/Glob.cs
@@ -0,0 +1,13 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace IRCSharp.Tests.Robots
+{
+ [TestClass]
+ public class Glob
+ {
+ [TestMethod]
+ public void GlobCollapse()
+ {
+ }
+ }
+}
diff --git a/IRCSharp.sln b/IRCSharp.sln
index 4f1539a..f7bf841 100644
--- a/IRCSharp.sln
+++ b/IRCSharp.sln
@@ -20,6 +20,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IRCSharp.Tests", "IRCSharp.
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{4260E03C-6E28-4519-8943-5B477841A75A}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IRCRobots", "IRCRobots\IRCRobots.csproj", "{BACE834E-B190-46F1-8687-E994316FF768}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robots", "Examples\Robots\Robots.csproj", "{932066DD-A44A-47EA-94F5-D7847CAA8EC7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -46,6 +50,14 @@ Global
{B420F0F3-1ED0-4FD3-9E91-2E7F96F9FF7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B420F0F3-1ED0-4FD3-9E91-2E7F96F9FF7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B420F0F3-1ED0-4FD3-9E91-2E7F96F9FF7F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BACE834E-B190-46F1-8687-E994316FF768}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BACE834E-B190-46F1-8687-E994316FF768}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BACE834E-B190-46F1-8687-E994316FF768}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BACE834E-B190-46F1-8687-E994316FF768}.Release|Any CPU.Build.0 = Release|Any CPU
+ {932066DD-A44A-47EA-94F5-D7847CAA8EC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {932066DD-A44A-47EA-94F5-D7847CAA8EC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {932066DD-A44A-47EA-94F5-D7847CAA8EC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {932066DD-A44A-47EA-94F5-D7847CAA8EC7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -53,6 +65,7 @@ Global
GlobalSection(NestedProjects) = preSolution
{A45DA39B-6B47-4713-8049-3B36E0235B67} = {4260E03C-6E28-4519-8943-5B477841A75A}
{BC9F6696-9D83-4F7A-9E15-CE4D3626C1AF} = {4260E03C-6E28-4519-8943-5B477841A75A}
+ {932066DD-A44A-47EA-94F5-D7847CAA8EC7} = {4260E03C-6E28-4519-8943-5B477841A75A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0B91F0EA-8564-4318-8EEC-ED0640475141}
diff --git a/IRCSharp.sln.DotSettings b/IRCSharp.sln.DotSettings
new file mode 100644
index 0000000..71c228c
--- /dev/null
+++ b/IRCSharp.sln.DotSettings
@@ -0,0 +1,7 @@
+
+ SASL
+ STS
+ TLS
+ True
+ True
+ True
\ No newline at end of file