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.
11 using System
.Collections
.Generic
;
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);
29 conn
.MessageReceived
+= MessageReceivedParsing
;
30 System
.Threading
.Thread
.Sleep(300);
31 conn
.SendRawMessage(Rfc
.Join(channelName
));
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;
56 if ((usertemp
= GetUserByName(temp
[0])) == null)
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;
67 if ((usertemp
= GetUserByName(temp
[0])) == null)
69 this.userList
.Remove(usertemp
);
70 OnUserDisconnected(new UserQuitEventArgs(temp
[1] ?? string.Empty
, usertemp
));
73 bakery
.Join
+= delegate(IrcChannel sender
, string[] infos
) {
75 if (infos
[0].Equals(this.ParentConnection
.Nick
, StringComparison
.Ordinal
))
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],
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;
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);
119 if (temp[0].Equals(this.ParentConnection.Nick, StringComparison.Ordinal))
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;
132 if ((usertemp = GetUserByName(temp[0])) == null)
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
150 #region Helper methods
151 private void AddInitialUsers(string[] names
)
154 throw new ArgumentNullException("names");
155 if (names
.Length
== 0)
156 throw new ArgumentException("names is empty");
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));
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
)
178 foreach (IrcUser user
in userList
) {
179 if (user
.Nick
== userName
) {