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 conn
.SendRawMessage(Rfc
.Join(channelName
));
35 // TODO: turn this into static call using the sender arg
36 bakery
.Message
= delegate(IrcChannel sender
, string[] args
) {
37 Logger
.Debug("Receiving message from " + sender
.Name
);
38 OnMessageReceived(new ChannelMessageEventArgs(args
[0], args
[1]));
41 bakery
.NewUserList
= delegate(IrcChannel sender
, string[] users
) {
42 Logger
.Debug("Receiving users list from " + sender
.Name
);
43 AddInitialUsers(users
);
46 bakery
.Topic
= delegate(IrcChannel sender
, string topic
) {
47 OnTopicUpdated(new TopicEventArgs(topic
));
50 bakery
.QuitOrPart
= delegate(IrcChannel sender
, string[] temp
) {
51 Logger
.Debug("An user has departed from " + sender
.Name
);
52 IrcUser usertemp
= null;
55 if ((usertemp
= GetUserByName(temp
[0])) == null)
57 this.userList
.Remove(usertemp
);
58 OnUserDisconnected(new UserQuitEventArgs(temp
[1] ?? string.Empty
, usertemp
));
61 bakery
.Join
= delegate(IrcChannel sender
, string[] infos
) {
63 if (infos
[0].Equals(this.ParentConnection
.Nick
, StringComparison
.Ordinal
))
66 bool halfOp
= infos
[0][0] == Rfc
.HalfOpChar
;
67 bool op
= infos
[0][0] == Rfc
.OpChar
|| infos
[0][0] == Rfc
.NetworkOp
;
69 IrcUser user
= new CilIrcUser((halfOp
|| op
) ? infos
[0].Substring(1) : infos
[0], infos
[1],
71 this.userList
.Add(user
);
73 OnNewUserConnected(new UserEventArgs(user
));
77 public override void SendMessage (string message
)
79 ParentConnection
.SendRawMessage(Rfc
.PrivMsg(Name
, message
));
82 protected override void CloseChannel (string byeMessage
)
84 ParentConnection
.SendRawMessage(Rfc
.Part(Name
, byeMessage
));
88 private void MessageReceivedParsing(object sender
, MessageEventArgs e
)
90 // Now evrything is handled via event
92 bakery
.PostNewMessage(e
.Message
);
94 bool isAction = parser.RetrieveMessageType(e.Message) == MessageType.Action;
95 ActionType action = (isAction) ? parser.RetrieveAction(e.Message) : (ActionType)0;
99 OnMessageReceived(new ChannelMessageEventArgs(parser.RetrieveAuthor(e.Message),
100 parser.RetrieveMessage(e.Message)));
101 else if (msgType == MessageType.Reply
102 && parser.RetrieveNumericalReply(e.Message) == Rfc.NamesReply && parser.RetrieveChannelTarget(e.Message) == this.Name)
103 AddInitialUsers(parser.RetrieveUsersList(e.Message));
104 else if (msgType == MessageType.Action && parser.RetrieveAction(e.Message) == ActionType.Join && parser.RetrieveChannelTarget(e.Message) == this.Name) {
105 string[] temp = parser.RetrieveJoinInformations(e.Message);
107 if (temp[0].Equals(this.ParentConnection.Nick, StringComparison.Ordinal))
110 IrcUser user = new CilIrcUser(temp[0], temp[1], this, false, temp[0][0] == Rfc.HalfOpChar);
111 this.userList.Add(user);
112 // TODO: handle op thing correctly
113 OnNewUserConnected(new UserEventArgs(user));
115 else if (msgType == MessageType.Action && parser.RetrieveAction(e.Message) == ActionType.Part && parser.RetrieveChannelTarget(e.Message) == this.Name) {
116 string[] temp = parser.RetrieveQuitInformations(e.Message);
117 IrcUser usertemp = null;
120 if ((usertemp = GetUserByName(temp[0])) == null)
122 this.userList.Remove(usertemp);
123 OnUserDisconnected(new UserQuitEventArgs(temp[1] ?? string.Empty, usertemp));
125 else if (msgType == MessageType.Reply
126 && parser.RetrieveNumericalReply(e.Message) == Rfc.TopicReply && parser.RetrieveChannelTarget(e.Message) == this.Name)
127 OnTopicUpdated(new TopicEventArgs(parser.RetrieveTopic(e.Message)));
128 } catch (Exception ex) {
129 Logger.Error("A message has been dropped", ex);
135 private void AddInitialUsers(string[] names
)
138 throw new ArgumentNullException("names");
139 if (names
.Length
== 0)
140 throw new ArgumentException("names is empty");
144 // HACK: WTF ? IndexOutOfRange even with names.Length
145 for (int i
= 0; i
< names
.Length
- 1; i
++) {
146 if (names
[i
][0] == Rfc
.HalfOpChar
)
147 userList
.Add(new CilIrcUser(names
[i
], "foo", this, true, false));
149 userList
.Add(new CilIrcUser(names
[i
], "foo", this, false, false));
152 OnNewUserList(new UserListEventArgs(userList
.ToArray()));
155 private IrcUser
GetUserByName(string userName
)
158 foreach (IrcUser user
in userList
) {
159 if (user
.Nick
== userName
) {