]> jfr.im git - z_archive/kelsier.git/blame - Kelsier.Common/Bot.cs
Adding auth
[z_archive/kelsier.git] / Kelsier.Common / Bot.cs
CommitLineData
e5993b94
JR
1// Kelsier project - Bot state and parser code (Bot.cs)
2// Written by the Jobbig codeteam. <http://jobbig.eu/code/>
3//
4// Copyright 2013 John Runyon.
5//
6// This file is part of the Kelsier project.
7//
8// Kelsier is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17//
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using MySql.Data.MySqlClient;
27using System.Net;
28using System.Net.Sockets;
29
30namespace Kelsier.Common {
31 public class Bot {
32 public int id { get; private set; }
33
34 public string nick { get; private set; }
35 public string ident { get; private set; }
36 public string realname { get; private set; }
37 public string localip { get; private set; }
38 public string server { get; private set; }
39 public int serverport { get; private set; }
40
41 private IPEndPoint local;
42
43 private Socket s;
44 public bool online { get; private set; }
45
46 public Logger log { get; private set; }
47 public Database db { get; private set; }
48
49 public char trigger;
50
51
52 public Bot(int id, Database db, Logger log) {
53 this.trigger = '!';
54
55 this.id = id;
56
57 this.log = new Logger(id.ToString("0000"), log);
58 this.db = db;
59
60 MySqlDataReader rdr = db.queryReader("SELECT nick, ident, realname, bindip, server, serverport FROM bots WHERE id = @id", new object[] { "@id", id });
61 rdr.Read();
62
63 this.nick = rdr.GetString("nick");
64 this.ident = rdr.GetString("ident");
65 this.realname = rdr.GetString("realname");
66
67 if (rdr.IsDBNull(rdr.GetOrdinal("bindip"))) {
68 this.localip = null;
69 this.local = new IPEndPoint(IPAddress.Any, 0);
70 } else {
71 this.localip = rdr.GetString("bindip");
72 this.local = new IPEndPoint(IPAddress.Parse(this.localip), 0);
73 }
74
75 this.server = rdr.GetString("server");
76 this.serverport = rdr.GetInt32("serverport");
77 }
78
79 public string connect() {
80 if (online) throw new InvalidStateException();
81
82 s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
83 s.Bind(local);
84 s.Connect(server, serverport);
85
86 register();
87
88 Stator rcvstate = new Stator();
89 s.BeginReceive(rcvstate.buffer, 0, 1, SocketFlags.None, new AsyncCallback(dataIn), rcvstate);
90
91 return "TODO";
92 }
93
94 public void dataIn(IAsyncResult ar) {
95 Stator rcvstate = (Stator)ar.AsyncState;
96 s.EndReceive(ar);
97
98 if (rcvstate.buffer[0] == '\n') {
99 string linein = rcvstate.buffersb.ToString();
100 processData(linein);
101 rcvstate = new Stator();
102 } else if (rcvstate.buffer[0] != '\r') {
103 rcvstate.buffersb.Append(Encoding.ASCII.GetString(rcvstate.buffer, 0, 1));
104 }
105 s.BeginReceive(rcvstate.buffer, 0, 1, SocketFlags.None, new AsyncCallback(dataIn), rcvstate);
106 }
107 private void send(string data, params object[] args) {
108 log.info(">>> " + data);
109 s.Send(Encoding.ASCII.GetBytes(data + "\n"));
110 }
111
112 private void processData(string data) {
113 log.info("<<< " + data);
114
115 string[] parts;
116 string source = null;
117 if (data.StartsWith(":")) {
118 parts = data.Split((char[])null, 2, StringSplitOptions.RemoveEmptyEntries);
119 source = parts[0].Substring(1);
120 data = parts[1];
121 }
122
123 parts = data.Split((char[])null, 2, StringSplitOptions.RemoveEmptyEntries);
124 if (parts[0] == "PRIVMSG") {
125 processMsg(source, parts[1]);
126 } else if (parts[0] == "376") {
127 send("JOIN #jobbig"); // TODO
128 } else if (parts[0] == "PING") {
129 send("PONG "+parts[1]);
130 }
131 }
132 // processMsg("DimeCadmium!dime@jobbig.eu", "#mustis :hi");
133 private void processMsg(string source, string data) {
134 string[] dataparts = data.Split((char[])null, 2, StringSplitOptions.RemoveEmptyEntries);
135
136 string nick = (source.Split(new char[] { '!' }))[0];
137 string target = dataparts[0];
138 string message = dataparts[1];
139 if (message.StartsWith(":"))
140 message = message.Substring(1);
141 string[] msgparts = message.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
142
143 if (msgparts[0][0] != trigger)
144 return;
145 string cmdstr = msgparts[0].Substring(1);
146 string[] args;
147 bool chanmsg;
148 Channel chan;
149 if (target.StartsWith("#")) {
150 chanmsg = true;
151 args = new string[msgparts.Length - 1];
152 Array.Copy(msgparts, 1, args, 0, msgparts.Length - 1);
153 chan = new Channel(target);
154 } else {
155 chanmsg = false;
156 args = new string[msgparts.Length - 2];
157 Array.Copy(msgparts, 2, args, 0, msgparts.Length - 2);
158 chan = new Channel(msgparts[1]);
159 }
160
161 User user = new User(nick);
162
163 Command cmd = new Command(this, cmdstr, args, user, chan, chanmsg);
164 }
165
166 private void register() {
167 send(String.Format("NICK {0}", nick));
168 send(String.Format("USER {0} * * :{1}", ident, realname));
169 online = true;
170 }
171 }
172
173 public class InvalidStateException : Exception { }
174
175 public class Stator {
176 public byte[] buffer = new byte[1];
177 public StringBuilder buffersb = new StringBuilder();
178 }
179}