void PrintGroupChatPresence(XmppGroupChatModel chat, PersonModel person, Presence pres) { Jid jid = pres.From; var msg = CreatePresenceUpdateMessage(person.ID, person, pres); Session.AddMessageToChat(chat, msg); // clone directly to muc person chat // don't care about real jid, that has its own presence packets var personChat = Session.GetChat(jid, ChatType.Person, this); if (personChat != null) { Session.AddMessageToChat(personChat, msg); } }
void OnGroupChatPresence(XmppGroupChatModel chat, Presence pres) { Jid jid = pres.From; var person = new PersonModel(jid, pres.From.Resource ?? pres.From, NetworkID, Protocol, this); PrintGroupChatPresence(chat, person, pres); switch (pres.Type) { case PresenceType.available: // don't do anything if the contact already exists if (chat.UnsafePersons.ContainsKey(person.ID)) { return; } // is the chat synced? add the new contact the regular way if (chat.IsSynced) { Session.AddPersonToGroupChat(chat, person); return; } chat.UnsafePersons.Add(person.ID, person); // did I join? then the chat roster is fully received if (pres.From.Resource == chat.OwnNickname || pres.MucUser.StatusCodes.Exists(x => x.Code == StatusCode.SelfPresence)) { if (pres.MucUser.StatusCodes.Exists(x => x.Code == StatusCode.ModifiedNick)) { // as per XEP-0045 7.2.3 Example 24 the server is // allowed to give us a different nick than we requested chat.OwnNickname = pres.From.Resource; } chat.IsJoining = false; // HACK: lower probability of sync race condition swallowing messages ThreadPool.QueueUserWorkItem(delegate { Thread.Sleep(1000); lock (this) { if (IsDisposed) { return; } chat.IsSynced = true; Session.SyncChat(chat); Session.EnableChat(chat); } }); } break; case PresenceType.unavailable: Session.RemovePersonFromGroupChat(chat, person); // did I leave? then I "probably" left the room if (pres.From.Resource == chat.OwnNickname) { Session.RemoveChat(chat); } break; case PresenceType.error: OnGroupChatPresenceError(chat, pres); break; } }
void OnGroupChatPresenceError(XmppGroupChatModel chat, Presence pres) { if (pres.Error != null && pres.Error.Type == ErrorType.cancel && pres.Error.Condition == ErrorCondition.Conflict) { // nickname already in use; autorejoin with _ appended JoinRoom(chat.ID, chat.OwnNickname + "_", chat.Password); return; } var msg = CreateGroupChatPresenceErrorMessage(pres); Session.AddMessageToChat(NetworkChat, msg); Session.RemoveChat(chat); }
MessageModel CreateGroupChatMessage(XmppGroupChatModel groupChat, PersonModel person, Message msg) { var builder = CreateMessageBuilder(); string msgstring; if (msg.Html != null) { msgstring = msg.Html.ToString(); } else { msgstring = msg.Body.Trim(); } if (msgstring.StartsWith("/me ")) { // leave the " " intact msgstring = msgstring.Substring(3); builder.AppendActionPrefix(); builder.AppendIdendityName(person); } else { builder.AppendSenderPrefix(person); } if (msg.Html != null) { builder.AppendHtmlMessage(msgstring); } else { builder.AppendMessage(msgstring); } // mark hilights only for OwnNickname, too builder.Me = new PersonModel( groupChat.OwnNickname, groupChat.OwnNickname, NetworkID, Protocol, this); builder.MarkHighlights(); if (msg.XDelay != null) { builder.TimeStamp = msg.XDelay.Stamp; } return builder.ToMessage(); }
void OnGroupChatMessageError(Message msg, XmppGroupChatModel chat) { var builder = CreateMessageBuilder(); // TODO: nicer formatting if (msg.Error.ErrorText != null) { builder.AppendErrorText(msg.Error.ErrorText); } else { builder.AppendErrorText(msg.Error.ToString()); } Session.AddMessageToChat(chat, builder.ToMessage()); }
private void _OnMessage(object sender, Message xmppMsg) { if (xmppMsg.Body == null) { return; } var delay = xmppMsg["delay"]; string stamp = null; if (delay != null) { stamp = delay.Attributes["stamp"].Value; } bool display = true; ChatModel chat = null; PersonModel person = null; if (xmppMsg.Type != XmppMessageType.groupchat) { string jid = xmppMsg.From.Bare; var contact = _RosterManager[jid]; string nickname = jid; if (contact != null && contact.Nickname != null) { nickname = contact.Nickname.Replace(" ", "_"); } PersonChatModel personChat = (PersonChatModel) Session.GetChat(jid, ChatType.Person, this); if (personChat == null) { person = new PersonModel(jid, nickname, NetworkID, Protocol, this); personChat = new PersonChatModel(person, jid, nickname, this); Session.AddChat(personChat); Session.SyncChat(personChat); } else { person = personChat.Person; } chat = personChat; } else { string group_jid = xmppMsg.From.Bare; string group_name = group_jid; string sender_jid = xmppMsg.From.ToString(); XmppGroupChatModel groupChat = (XmppGroupChatModel) Session.GetChat(group_jid, ChatType.Group, this); if (groupChat == null) { // FIXME shouldn't happen? groupChat = new XmppGroupChatModel(group_jid, group_name, this); Session.AddChat(groupChat); Session.SyncChat(groupChat); } person = groupChat.GetPerson(xmppMsg.From.Resource); if (person == null) { // happens in case of a delayed message if the participant has left meanwhile person = new PersonModel(xmppMsg.From.Resource, xmppMsg.From.Resource, NetworkID, Protocol, this); } // XXX maybe only a Google Talk bug requires this: if (stamp != null) { // XXX can't use > because of seconds precision :-( if (stamp.CompareTo(groupChat.LatestSeenStamp) >= 0) { groupChat.LatestSeenStamp = stamp; } else { display = false; // already seen newer delayed message } if (groupChat.SeenNewMessages) { display = false; // already seen newer messages } } else { groupChat.SeenNewMessages = true; } chat = groupChat; } if (display) { var builder = CreateMessageBuilder(); if (xmppMsg.Type != XmppMessageType.error) { builder.AppendMessage(person, xmppMsg.Body); } else { // TODO: nicer formatting builder.AppendMessage(xmppMsg.Error.ToString()); } var msg = builder.ToMessage(); if (stamp != null) { string format = DateTimeFormatInfo.InvariantInfo.UniversalSortableDateTimePattern.Replace(" ", "T"); msg.TimeStamp = DateTime.ParseExact(stamp, format, null); } Session.AddMessageToChat(chat, msg); } }
void OnGroupChatPresenceError(XmppGroupChatModel chat, Presence pres) { var msg = CreateGroupChatPresenceErrorMessage(pres); if (pres.Error == null) { Session.AddMessageToChat(NetworkChat, msg); Session.RemoveChat(chat); } // is there an action we can do silently? switch (pres.Error.Type) { case ErrorType.cancel: switch (pres.Error.Condition) { case ErrorCondition.Conflict: // nickname already in use // autorejoin with _ appended to nickname JoinRoom(chat.ID, chat.OwnNickname + "_", chat.Password); return; } break; } Session.AddMessageToChat(NetworkChat, msg); Session.RemoveChat(chat); }
private void AddPersonToGroup(Room room, string nickname) { string jid = room.JID.Bare; var chat = (GroupChatModel) Session.GetChat(jid, ChatType.Group, this); // first notice we're joining a group chat is the participant info: if (chat == null) { chat = new XmppGroupChatModel(jid, jid, this); Session.AddChat(chat); Session.SyncChat(chat); } PersonModel person; lock(chat.UnsafePersons) { person = chat.GetPerson(nickname); if (person != null) { return; } person = new PersonModel(nickname, nickname, NetworkID, Protocol, this); chat.UnsafePersons.Add(nickname, person); Session.AddPersonToGroupChat(chat, person); } }
void OnGroupChatPresenceError(XmppGroupChatModel chat, Presence pres) { var builder = CreateMessageBuilder(); if (pres.Error == null) { builder.AppendErrorText(_("An unknown groupchat error occurred: {0}"), pres); Session.AddMessageToChat(NetworkChat, builder.ToMessage()); return; } switch (pres.Error.Type) { case ErrorType.cancel: switch (pres.Error.Condition) { case ErrorCondition.Conflict: // nickname already in use // autorejoin with _ appended to nickname JoinRoom(chat.ID, chat.OwnNickname + "_", chat.Password); return; } break; } if (String.IsNullOrEmpty(pres.Error.ErrorText)) { builder.AppendErrorText(_("An unhandled groupchat error occurred: {0}"), pres); } else { builder.AppendErrorText(_("Error in Groupchat {0}: {1}"), chat.ID, pres.Error.ErrorText); } Session.AddMessageToChat(NetworkChat, builder.ToMessage()); Session.RemoveChat(chat); }
private void OnMessage(object sender, Message msg) { if (msg.Body == null) { return; } var delay = msg["delay"]; string stamp = null; if (delay != null) { stamp = delay.Attributes["stamp"].Value; } bool display = true; ChatModel chat = null; PersonModel person = null; if (msg.Type != XmppMessageType.groupchat) { string jid = msg.From.Bare; var contact = _RosterManager[jid]; string nickname = null; if (contact == null || String.IsNullOrEmpty(contact.Nickname)) { nickname = jid; } else { nickname = contact.Nickname; } PersonChatModel personChat = (PersonChatModel)Session.GetChat(jid, ChatType.Person, this); if (personChat == null) { person = new PersonModel(jid, nickname, NetworkID, Protocol, this); personChat = Session.CreatePersonChat( person, jid, nickname, this ); Session.AddChat(personChat); Session.SyncChat(personChat); } else { person = personChat.Person; } chat = personChat; } else { string group_jid = msg.From.Bare; string group_name = group_jid; string sender_jid = msg.From.ToString(); XmppGroupChatModel groupChat = (XmppGroupChatModel)Session.GetChat(group_jid, ChatType.Group, this); if (groupChat == null) { // FIXME shouldn't happen? groupChat = Session.CreateChat <XmppGroupChatModel>( group_jid, group_name, this ); Session.AddChat(groupChat); Session.SyncChat(groupChat); } person = groupChat.GetPerson(msg.From.Resource); if (person == null) { // happens in case of a delayed message if the participant has left meanwhile person = new PersonModel(msg.From.Resource, msg.From.Resource, NetworkID, Protocol, this); } // XXX maybe only a Google Talk bug requires this: if (stamp != null) { // XXX can't use > because of seconds precision :-( if (stamp.CompareTo(groupChat.LatestSeenStamp) >= 0) { groupChat.LatestSeenStamp = stamp; } else { display = false; // already seen newer delayed message } if (groupChat.SeenNewMessages) { display = false; // already seen newer messages } } else { groupChat.SeenNewMessages = true; } chat = groupChat; } if (display) { var builder = CreateMessageBuilder(); if (msg.Type != XmppMessageType.error) { builder.AppendMessage(person, msg.Body); } else { // TODO: nicer formatting builder.AppendMessage(msg.Error.ToString()); } if (stamp != null) { string format = DateTimeFormatInfo.InvariantInfo.UniversalSortableDateTimePattern.Replace(" ", "T"); builder.TimeStamp = DateTime.ParseExact(stamp, format, null); } Session.AddMessageToChat(chat, builder.ToMessage()); } }
void PrintGroupChatPresence(XmppGroupChatModel chat, XmppPersonModel person, Presence pres) { Jid jid = pres.From; XmppResourceModel resource; if (person.MucResources.TryGetValue(jid.Resource??"", out resource)) { if (resource.Presence.Show == pres.Show && resource.Presence.Status == pres.Status && resource.Presence.Last == pres.Last && resource.Presence.XDelay == pres.XDelay && resource.Presence.Priority == pres.Priority && resource.Presence.Nickname == pres.Nickname && resource.Presence.Type == pres.Type ) { // presence didn't change enough to warrent a display message -> abort return; } } var msg = CreatePresenceUpdateMessage(person.Jid, person, pres); Session.AddMessageToChat(chat, msg); // clone directly to muc person chat // don't care about real jid, that has its own presence packets var personChat = Session.GetChat(jid, ChatType.Person, this); if (personChat != null) { Session.AddMessageToChat(personChat, msg); } }
void OnGroupChatPresence(XmppGroupChatModel chat, Presence pres) { Jid jid = pres.From; XmppPersonModel person; // check whether we know the real jid of this muc user if (pres.MucUser != null && pres.MucUser.Item != null && pres.MucUser.Item.Jid != null ) { string nick = pres.From.Resource; if (!string.IsNullOrEmpty(pres.MucUser.Item.Nickname)) { nick = pres.MucUser.Item.Nickname; } person = GetOrCreateContact(pres.MucUser.Item.Jid.Bare, nick); } else { // we do not know the real jid of this user, don't add it to our local roster // BUG? pres.From.Resource can be null? person = new XmppPersonModel(jid, pres.From.Resource, this); } person.GetOrCreateMucResource(jid).Presence = pres; PrintGroupChatPresence(chat, person, pres); switch (pres.Type) { case PresenceType.available: // don't do anything if the contact already exists if (chat.UnsafePersons.ContainsKey(person.ID)) { return; } // is the chat synced? add the new contact the regular way if (chat.IsSynced) { Session.AddPersonToGroupChat(chat, person.ToPersonModel()); return; } chat.UnsafePersons.Add(person.ID, person.ToPersonModel()); // did I join? then the chat roster is fully received if (pres.From.Resource == chat.OwnNickname) { // HACK: lower probability of sync race condition swallowing messages ThreadPool.QueueUserWorkItem(delegate { Thread.Sleep(1000); lock (this) { if (IsDisposed) { return; } chat.IsSynced = true; Session.SyncChat(chat); Session.EnableChat(chat); } }); } break; case PresenceType.unavailable: Session.RemovePersonFromGroupChat(chat, person.ToPersonModel()); // did I leave? then I "probably" left the room if (pres.From.Resource == chat.OwnNickname) { Session.RemoveChat(chat); } break; case PresenceType.error: if (pres.Error == null) break; switch (pres.Error.Type) { case ErrorType.cancel: switch (pres.Error.Condition) { case ErrorCondition.Conflict: // nickname already in use // autorejoin with _ appended to nickname JoinRoom(chat.ID, chat.OwnNickname + "_", chat.Password); break; } break; } break; } }