* Corrected small things to make Circ-git compile from within MonoDevelop
[circ.git] / Circ.Backend.Cil / CilIrcChannel.cs
blob4368d3f32040eea2e30ad27c390e4f69abb786c5
1 #region License
2 /* Circ.Cil : Circ's Irc Library, main backend for Circ
3 * Copyright (C) 2007 LAVAL Jérémie
5 * This file is licensed under the terms of the LGPL.
7 * For the complete licence see the file COPYING.
8 */
9 #endregion
10 using System;
11 using System.Collections.Generic;
12 using Circ.Backend;
14 namespace Circ.Cil
16 public class CilIrcChannel: IrcChannel
18 IParser parser = DefaultParser.Instance;
19 // TODO: Maybe replace the List with a Dictionary for better performance since user are mainly manipulated
20 // with their nickname string
21 List<IrcUser> userList = new List<IrcUser>();
22 ChannelMessageBakery bakery;
24 internal CilIrcChannel(string channelName, IrcConnection conn)
25 : base(channelName, conn)
27 bakery = new ChannelMessageBakery(this);
28 InitBakery();
29 conn.MessageReceived += MessageReceivedParsing;
30 System.Threading.Thread.Sleep(300);
31 conn.SendRawMessage(Rfc.Join(channelName));
34 void InitBakery()
36 // TODO: turn this into static call using the sender arg
37 bakery.Message += delegate(IrcChannel sender, string[] args) {
38 Logger.Debug("Receiving message from " + sender.Name);
39 OnMessageReceived(new ChannelMessageEventArgs(args[0], args[1]));
42 bakery.NewList += delegate(IrcChannel sender, string[] users) {
43 Logger.Debug("Receiving users list from " + sender.Name);
44 AddInitialUsers(users);
47 bakery.Topic += delegate(IrcChannel sender, string topic) {
48 OnTopicUpdated(new TopicEventArgs(topic));
51 bakery.Quit += delegate(IrcChannel sender, string[] temp) {
52 Logger.Debug("An user has departed from " + sender.Name);
53 IrcUser usertemp = null;
54 if (temp[0] == null)
55 return;
56 if ((usertemp = GetUserByName(temp[0])) == null)
57 return;
58 this.userList.Remove(usertemp);
59 OnUserDisconnected(new UserQuitEventArgs(temp[1] ?? string.Empty, usertemp));
62 bakery.Part += delegate(IrcChannel sender, string[] temp) {
63 Logger.Debug("An user has departed from " + sender.Name);
64 IrcUser usertemp = null;
65 if (temp[0] == null)
66 return;
67 if ((usertemp = GetUserByName(temp[0])) == null)
68 return;
69 this.userList.Remove(usertemp);
70 OnUserDisconnected(new UserQuitEventArgs(temp[1] ?? string.Empty, usertemp));
73 bakery.Join += delegate(IrcChannel sender, string[] infos) {
74 // Dont add ourself
75 if (infos[0].Equals(this.ParentConnection.Nick, StringComparison.Ordinal))
76 return;
78 bool halfOp = infos[0][0] == Rfc.HalfOpChar;
79 bool op = infos[0][0] == Rfc.OpChar || infos[0][0] == Rfc.NetworkOp;
81 IrcUser user = new CilIrcUser((halfOp || op) ? infos[0].Substring(1) : infos[0], infos[1],
82 this, op, halfOp);
83 this.userList.Add(user);
85 OnNewUserConnected(new UserEventArgs(user));
89 public override void SendMessage (string message)
91 ParentConnection.SendRawMessage(Rfc.PrivMsg(Name, message));
94 protected override void SendQuitMessage (string byeMessage)
96 ParentConnection.SendRawMessage(Rfc.Part(Name, byeMessage));
100 private void MessageReceivedParsing(object sender, MessageEventArgs e)
102 // Now evrything is handled via event
104 bakery.PostNewMessage(e.Message);
106 bool isAction = parser.RetrieveMessageType(e.Message) == MessageType.Action;
107 ActionType action = (isAction) ? parser.RetrieveAction(e.Message) : (ActionType)0;
109 try {
110 if ()
111 OnMessageReceived(new ChannelMessageEventArgs(parser.RetrieveAuthor(e.Message),
112 parser.RetrieveMessage(e.Message)));
113 else if (msgType == MessageType.Reply
114 && parser.RetrieveNumericalReply(e.Message) == Rfc.NamesReply && parser.RetrieveChannelTarget(e.Message) == this.Name)
115 AddInitialUsers(parser.RetrieveUsersList(e.Message));
116 else if (msgType == MessageType.Action && parser.RetrieveAction(e.Message) == ActionType.Join && parser.RetrieveChannelTarget(e.Message) == this.Name) {
117 string[] temp = parser.RetrieveJoinInformations(e.Message);
118 // Dont add ourself
119 if (temp[0].Equals(this.ParentConnection.Nick, StringComparison.Ordinal))
120 return;
122 IrcUser user = new CilIrcUser(temp[0], temp[1], this, false, temp[0][0] == Rfc.HalfOpChar);
123 this.userList.Add(user);
124 // TODO: handle op thing correctly
125 OnNewUserConnected(new UserEventArgs(user));
127 else if (msgType == MessageType.Action && parser.RetrieveAction(e.Message) == ActionType.Part && parser.RetrieveChannelTarget(e.Message) == this.Name) {
128 string[] temp = parser.RetrieveQuitInformations(e.Message);
129 IrcUser usertemp = null;
130 if (temp[0] == null)
131 return;
132 if ((usertemp = GetUserByName(temp[0])) == null)
133 return;
134 this.userList.Remove(usertemp);
135 OnUserDisconnected(new UserQuitEventArgs(temp[1] ?? string.Empty, usertemp));
137 else if (msgType == MessageType.Reply
138 && parser.RetrieveNumericalReply(e.Message) == Rfc.TopicReply && parser.RetrieveChannelTarget(e.Message) == this.Name)
139 OnTopicUpdated(new TopicEventArgs(parser.RetrieveTopic(e.Message)));
140 } catch (Exception ex) {
141 Logger.Error("A message has been dropped", ex);
145 #region worker methods
148 #endregion
150 #region Helper methods
151 private void AddInitialUsers(string[] names)
153 if (names == null)
154 throw new ArgumentNullException("names");
155 if (names.Length == 0)
156 throw new ArgumentException("names is empty");
158 userList.Clear();
160 // HACK: WTF ? IndexOutOfRange even with names.Length
161 for (int i = 0; i< names.Length - 1; i++) {
162 if (names[i][0] == Rfc.HalfOpChar)
163 userList.Add(new CilIrcUser(names[i].Substring(1), "foo", this, false, true));
164 else if (names[i][0] == Rfc.OpChar)
165 userList.Add(new CilIrcUser(names[i].Substring(1), "foo", this, true, false));
166 else
167 userList.Add(new CilIrcUser(names[i], "foo", this, false, false));
170 IrcUser[] temp = userList.ToArray();
172 OnNewUserList(new UserListEventArgs(userList.ToArray()));
175 private IrcUser GetUserByName(string userName)
177 IrcUser temp = null;
178 foreach (IrcUser user in userList) {
179 if (user.Nick == userName) {
180 temp = user;
181 break;
184 return temp;
186 #endregion