/// <summary> /// Parses and handles a "clientlist" response and updates the dictionary of client ID/nicknames /// </summary> /// <param name="clientList">The client list response</param> private void AddClients(string clientList) { var clientStrings = clientList.Split('|'); foreach (var clientString in clientStrings) { if (clientString.Contains(Properties.ClientID) && clientString.Contains(Properties.ClientNickname)) { uint clientId = DecodeUtility.DecodeUIntProperty(clientString, Properties.ClientID); string clientNickname = DecodeUtility.DecodeStringProperty(clientString, true, Properties.ClientNickname); uint channelId = 0; if (clientString.Contains(Properties.ChannelID) || clientString.Contains(Properties.TargetChannelID)) { channelId = DecodeUtility.DecodeUIntProperty(clientString, Properties.ChannelID, Properties.TargetChannelID); } var client = new Client(clientId, clientNickname, channelId); this.clients.AddOrUpdate(clientId, client, (key, oldValue) => client); // If they joined the current channel, raise the client entered channel event if (client.ChannelID == this.CurrentChannelID) { this.localClients.AddOrUpdate(clientId, this.clients[clientId], (key, oldValue) => this.clients[clientId]); this.RaiseClientEnteredChannel(new Data.ClientEventArgs(clientId, this.clients[clientId].Name)); } } } }
/// <summary> /// Parses and handles a text message notification string /// </summary> /// <param name="notificationString">The text message notification string to parse</param> private void HandleTextMessage(string notificationString) { var notificationProperties = notificationString.Split(' '); uint clientId = uint.Parse(notificationProperties.First(id => id.StartsWith(Properties.InvokerID)).Substring(Properties.InvokerID.Length + 1)); string clientNickname = DecodeUtility.DecodeString(notificationProperties.First(id => id.StartsWith(Properties.InvokerName)).Substring(Properties.InvokerName.Length + 1)); string message = DecodeUtility.DecodeString(notificationProperties.First(id => id.StartsWith(Properties.Message)).Substring(Properties.Message.Length + 1)); // Raise the text message received event logger.Trace("Text message received From {0} ({1}): {2}", clientId, clientNickname, message); this.RaiseTextMessageReceived(new Data.TextMessageEventArgs(clientId, clientNickname, message)); }
/// <summary> /// Handles the ClientUpdated TS notification /// </summary> /// <param name="notificationString">The notification string</param> private void HandleClientUpdated(string notificationString) { // Someone changed their nickname if (notificationString.Contains(Properties.ClientNickname)) { uint clientId = DecodeUtility.DecodeUIntProperty(notificationString, Properties.ClientID); if (this.clients.ContainsKey(clientId)) { string clientNickname = DecodeUtility.DecodeStringProperty(notificationString, true, Properties.ClientNickname); this.clients[clientId].Name = clientNickname; } } }
/// <summary> /// Sends a request for the current server information and raises the server connected event /// </summary> private void RequestCurrentServerInfo() { // Determine the current server information logger.Info("Requesting current server information"); string result = this.TsConnection.SendCommand(new Command("servervariable " + Properties.ServerName + " " + Properties.ServerIP)); if (!string.IsNullOrEmpty(result)) { string serverName = DecodeUtility.DecodeStringProperty(result, true, Properties.ServerName); string serverAddress = DecodeUtility.DecodeStringProperty(result, false, Properties.ServerIP); logger.Info("Server Information: name={0} address={1}", serverName, serverAddress); this.RaiseNewServerInfo(new NewServerInfoEventArgs(serverName, serverAddress)); } }
/// <summary> /// Handles the ClientExitedView TS notification /// </summary> /// <param name="notificationString">The notification string</param> private void HandleClientExitedView(string notificationString) { // Someone left the server var clientId = DecodeUtility.DecodeUIntProperty(notificationString, Properties.ClientID); Client client; if (this.clients.TryRemove(clientId, out client)) { if (client.ChannelID == this.currentChannelID) { // They were in our channel, so raise the client left channel event Client throwAway; this.localClients.TryRemove(clientId, out throwAway); this.RaiseClientExitedChannel(new Data.ClientEventArgs(clientId, client.Name)); } } }
internal static Channel FromChannelString(string channelString) { var parts = channelString.Split(' ', '\n', '\r'); uint id = DecodeUtility.DecodeUIntProperty(channelString, Properties.ChannelID); uint parentId = 0; if (parts.FirstOrDefault(part => part.StartsWith(Properties.ParentID)) != null || parts.FirstOrDefault(part => part.StartsWith(Properties.ChannelParentID)) != null) { parentId = DecodeUtility.DecodeUIntProperty(channelString, Properties.ParentID, Properties.ChannelParentID); } uint order = 0; if (parts.FirstOrDefault(part => part.StartsWith(Properties.ChannelOrder)) != null) { order = DecodeUtility.DecodeUIntProperty(channelString, Properties.ChannelOrder); } string name = string.Empty; if (parts.FirstOrDefault(part => part.StartsWith(Properties.ChannelName)) != null) { name = DecodeUtility.DecodeStringProperty(channelString, true, Properties.ChannelName); } uint clientsCount = 0; if (parts.FirstOrDefault(part => part.StartsWith(Properties.ChannelClientsCount)) != null) { clientsCount = DecodeUtility.DecodeUIntProperty(channelString, Properties.ChannelClientsCount); } bool isSpacer = SpacerInfo.Parse(name) != null; Channel channelInfo = new Channel(id, name, isSpacer) { ParentID = parentId, Order = order, ClientsCount = clientsCount }; return(channelInfo); }
/// <summary> /// Sends a request for the current channel and raises the channel switched event /// </summary> private void RequestCurrentChannelInfo() { logger.Info("Requesting current channel information"); var command = new Command(string.Format("channelvariable {0}={1} {2} {3}", Properties.ChannelID, this.currentChannelID, Properties.ChannelName, Properties.ChannelDescription)); string result = this.TsConnection.SendCommand(command); if (!string.IsNullOrEmpty(result)) { // Parse the channel info string channelName = DecodeUtility.DecodeStringProperty(result, true, Properties.ChannelName); string channelDescription = DecodeUtility.DecodeStringProperty(result, true, Properties.ChannelDescription); logger.Info("Channel Information: name={0} description={1}", channelName, channelDescription); this.RaiseClientChannelChanged(new ChannelEventArgs(new Channel(this.currentChannelID, channelName) { Description = channelDescription })); } }
/// <summary> /// Handles the ClientMoved TS notification /// </summary> /// <param name="notificationString">The notification string</param> private void HandleClientMoved(string notificationString) { // Client moved channel if (this.currentClientID == DecodeUtility.DecodeUIntProperty(notificationString, Properties.ClientID)) { // The current user moved channel, so update our current channel uint prevChannelId = this.currentChannelID; uint channelId = DecodeUtility.DecodeUIntProperty(notificationString, Properties.ChannelID, Properties.TargetChannelID); this.currentChannelID = channelId; logger.Trace("New Channel ID: {0}", this.currentChannelID); this.RequestCurrentChannelInfo(); foreach (var client in this.localClients.Values) { this.RaiseClientExitedChannel(new ClientEventArgs(client.ID, client.Name)); } this.localClients.Clear(); // Also raise channel updated for the channel that lost the client and the channel that gained the client if (this.channels.ContainsKey(prevChannelId)) { this.channels[prevChannelId].ClientsCount--; this.RaiseChannelUpdated(new ChannelEventArgs(this.channels[prevChannelId])); } if (this.channels.ContainsKey(this.currentChannelID)) { this.channels[this.currentChannelID].ClientsCount++; this.RaiseChannelUpdated(new ChannelEventArgs(this.channels[this.currentChannelID])); } // Request the client list for the current channel Task.Factory.StartNew(() => { string result = this.TsConnection.SendCommand(new Command("clientlist")); if (!string.IsNullOrEmpty(result)) { this.AddClients(result); } }); } else { // Someone else moved - raise the client entered/exited based on what channel they moved to uint clientId = DecodeUtility.DecodeUIntProperty(notificationString, Properties.ClientID); uint newChannelId = DecodeUtility.DecodeUIntProperty(notificationString, Properties.ChannelID, Properties.TargetChannelID); uint prevChannelId = 0; if (this.clients.ContainsKey(clientId)) { prevChannelId = this.clients[clientId].ChannelID; if (this.localClients.ContainsKey(clientId)) { // Someone left the channel Client throwAway; this.localClients.TryRemove(clientId, out throwAway); this.RaiseClientExitedChannel(new Data.ClientEventArgs(clientId, this.clients[clientId].Name)); } else if (newChannelId == this.currentChannelID) { // Someone joined the channel this.localClients.AddOrUpdate(clientId, this.clients[clientId], (key, oldValue) => this.clients[clientId]); this.RaiseClientEnteredChannel(new Data.ClientEventArgs(clientId, this.clients[clientId].Name)); } this.clients[clientId].ChannelID = newChannelId; } else { this.AddClients(notificationString); } // Also raise channel updated for the channel that lost the client and the channel that gained the client if (this.channels.ContainsKey(prevChannelId)) { this.channels[prevChannelId].ClientsCount--; this.RaiseChannelUpdated(new ChannelEventArgs(this.channels[prevChannelId])); } if (this.channels.ContainsKey(newChannelId)) { this.channels[newChannelId].ClientsCount++; this.RaiseChannelUpdated(new ChannelEventArgs(this.channels[newChannelId])); } } }