public bool AddOfflineMessage(GridInstantMessage message)
        {
            object remoteValue = DoRemote(message);
            if (remoteValue != null || m_doRemoteOnly)
                return remoteValue == null ? false : (bool) remoteValue;

            if (m_maxOfflineMessages <= 0 ||
                GenericUtils.GetGenericCount(message.ToAgentID, "OfflineMessages", GD) < m_maxOfflineMessages)
            {
                GenericUtils.AddGeneric(message.ToAgentID, "OfflineMessages", UUID.Random().ToString(),
                                        message.ToOSD(), GD);
                return true;
            }
            return false;
        }
        public override void FromOSD(OSDMap map)
        {
            AgentInfo = new IAgentInfo();
            AgentInfo.FromOSD((OSDMap) (map["AgentInfo"]));
            UserAccount = new UserAccount();
            UserAccount.FromOSD((OSDMap) (map["UserAccount"]));
            if (!map.ContainsKey("ActiveGroup"))
                ActiveGroup = null;
            else
            {
                ActiveGroup = new GroupMembershipData();
                ActiveGroup.FromOSD((OSDMap) (map["ActiveGroup"]));
            }
            GroupMemberships = ((OSDArray) map["GroupMemberships"]).ConvertAll<GroupMembershipData>((o) =>
                                                                                                        {
                                                                                                            GroupMembershipData
                                                                                                                group =
                                                                                                                    new GroupMembershipData
                                                                                                                        ();
                                                                                                            group
                                                                                                                .FromOSD
                                                                                                                ((OSDMap
                                                                                                                 ) o);
                                                                                                            return group;
                                                                                                        });
            OfflineMessages = ((OSDArray) map["OfflineMessages"]).ConvertAll<GridInstantMessage>((o) =>
                                                                                                     {
                                                                                                         GridInstantMessage
                                                                                                             group =
                                                                                                                 new GridInstantMessage
                                                                                                                     ();
                                                                                                         group.FromOSD(
                                                                                                             (OSDMap) o);
                                                                                                         return group;
                                                                                                     });
            MuteList = ((OSDArray) map["MuteList"]).ConvertAll<MuteList>((o) =>
                                                                             {
                                                                                 MuteList group = new MuteList();
                                                                                 group.FromOSD((OSDMap) o);
                                                                                 return group;
                                                                             });

            if (map.ContainsKey("Appearance"))
            {
                Appearance = new AvatarAppearance();
                Appearance.FromOSD((OSDMap)map["Appearance"]);
            }
        }
        public void llGiveInventoryList(string destination, string category, LSL_List inventory)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;

            UUID destID;
            if (!UUID.TryParse(destination, out destID))
                return;

            List<UUID> itemList = new List<UUID>();

            foreach (Object item in inventory.Data)
            {
                UUID itemID;
                if (UUID.TryParse(item.ToString(), out itemID))
                {
                    itemList.Add(itemID);
                }
                else
                {
                    itemID = GetTaskInventoryItem(item.ToString());
                    if (itemID != UUID.Zero)
                        itemList.Add(itemID);
                }
            }

            if (itemList.Count == 0)
                return;
            UUID folderID = UUID.Zero;
            ILLClientInventory inventoryModule = World.RequestModuleInterface<ILLClientInventory>();
            if (inventoryModule != null)
                folderID = inventoryModule.MoveTaskInventoryItemsToUserInventory(destID, category, m_host, itemList);

            if (folderID == UUID.Zero)
                return;

            byte[] bucket = new byte[17];
            bucket[0] = (byte) AssetType.Folder;
            byte[] objBytes = folderID.GetBytes();
            Array.Copy(objBytes, 0, bucket, 1, 16);

            GridInstantMessage msg = new GridInstantMessage()
                {
                    FromAgentID = m_host.UUID,
                    FromAgentName = m_host.Name + ", an object owned by " +
                                                                         resolveName(m_host.OwnerID) + ",",
                    ToAgentID = destID,
                    Dialog = (byte)InstantMessageDialog.InventoryOffered,
                    Message = category + "\n" + m_host.Name + " is located at " +
                                                                   World.RegionInfo.RegionName + " " +
                                                                   m_host.AbsolutePosition.ToString(),
                    SessionID = folderID,
                    Offline = 1,
                    Position = m_host.AbsolutePosition,
                    BinaryBucket = bucket,
                    RegionID = m_host.ParentEntity.Scene.RegionInfo.RegionID
                };

            if (m_TransferModule != null)
                m_TransferModule.SendInstantMessage(msg);
        }
        public void DropMemberFromSession(UUID agentID, GridInstantMessage im)
        {
            if (m_doRemoteOnly)
            {
                DoRemoteCallPost(true, "InstantMessageServerURI", agentID, im);
                return;
            }

            ChatSession session;
            ChatSessions.TryGetValue(im.SessionID, out session);
            if (session == null)
                return;
            ChatSessionMember member = null;
            foreach (
                ChatSessionMember testmember in
                    session.Members.Where(testmember => testmember.AvatarKey == im.FromAgentID))
                member = testmember;

            if (member == null)
                return;

            member.HasBeenAdded = false;
            member.RequestedRemoval = true;

            if (session.Members.Count(mem => mem.HasBeenAdded) == 0) //If a member hasn't been added, kill this anyway
            {
                ChatSessions.Remove(session.SessionID);
                return;
            }

            ChatterBoxSessionAgentListUpdatesMessage.AgentUpdatesBlock block =
                new ChatterBoxSessionAgentListUpdatesMessage.AgentUpdatesBlock
                    {
                        AgentID = member.AvatarKey,
                        CanVoiceChat = member.CanVoiceChat,
                        IsModerator = member.IsModerator,
                        MuteText = member.MuteText,
                        MuteVoice = member.MuteVoice,
                        Transition = "LEAVE"
                    };
            foreach (ChatSessionMember sessionMember in session.Members)
            {
                if (sessionMember.HasBeenAdded) //Only send to those in the group
                {
                    UUID regionID = FindRegionID(sessionMember.AvatarKey);
                    if (regionID != UUID.Zero)
                    {
                        m_eventQueueService.ChatterBoxSessionAgentListUpdates(session.SessionID, new[] {block},
                                                                              sessionMember.AvatarKey, "LEAVE",
                                                                              regionID);
                    }
                }
            }
        }
        public DateTime llGiveInventory(string destination, string inventory)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
                return DateTime.Now;

            bool found = false;
            UUID destId = UUID.Zero;
            UUID objId = UUID.Zero;
            int assetType = 0;
            string objName = String.Empty;

            if (!UUID.TryParse(destination, out destId))
            {
                llSay(0, "Could not parse key " + destination);
                return DateTime.Now;
            }

            // move the first object found with this inventory name
            lock (m_host.TaskInventory)
            {
                foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
                {
                    if (inv.Value.Name == inventory)
                    {
                        found = true;
                        objId = inv.Key;
                        assetType = inv.Value.Type;
                        objName = inv.Value.Name;
                        break;
                    }
                }
            }

            if (!found)
            {
                llSay(0, String.Format("Could not find object '{0}'", inventory));
                throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
            }

            // check if destination is an avatar
            if (World.GetScenePresence(destId) != null ||
                m_host.ParentEntity.Scene.RequestModuleInterface<IAgentInfoService>().GetUserInfo(destId.ToString()) !=
                null)
            {
                // destination is an avatar
                InventoryItemBase agentItem = null;
                ILLClientInventory inventoryModule = World.RequestModuleInterface<ILLClientInventory>();
                if (inventoryModule != null)
                    agentItem = inventoryModule.MoveTaskInventoryItemToUserInventory(destId, UUID.Zero, m_host, objId,
                                                                                     false);

                if (agentItem == null)
                    return DateTime.Now;

                byte[] bucket = new byte[17];
                bucket[0] = (byte) assetType;
                byte[] objBytes = agentItem.ID.GetBytes();
                Array.Copy(objBytes, 0, bucket, 1, 16);

                GridInstantMessage msg = new GridInstantMessage()
                    {
                        FromAgentID = m_host.UUID,
                        FromAgentName = m_host.Name + ", an object owned by " +
                                                                              resolveName(m_host.OwnerID) + ",",
                        ToAgentID = destId,
                        Dialog = (byte)InstantMessageDialog.InventoryOffered,
                        Message = objName + "'\n'" + m_host.Name + "' is located at " +
                                                                 m_host.AbsolutePosition.ToString() + " in '" +
                                                                 World.RegionInfo.RegionName,
                        SessionID = agentItem.ID,
                        Offline = 1,
                        Position = m_host.AbsolutePosition,
                        BinaryBucket = bucket,
                        RegionID = m_host.ParentEntity.Scene.RegionInfo.RegionID
                    };

                if (m_TransferModule != null)
                    m_TransferModule.SendInstantMessage(msg);
            }
            else
            {
                // destination is an object
                ILLClientInventory inventoryModule = World.RequestModuleInterface<ILLClientInventory>();
                if (inventoryModule != null)
                    inventoryModule.MoveTaskInventoryItemToObject(destId, m_host, objId);
            }
            return PScriptSleep(3000);
        }
        protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im)
        {
            GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync;

            d.BeginInvoke(im, null, GridInstantMessageCompleted, d);
        }
        private OSDMap syncRecievedService_OnMessageReceived(OSDMap message)
        {
            string method = message["Method"];
            if (method == "SendInstantMessages")
            {
                List<GridInstantMessage> messages =
                    ((OSDArray) message["Messages"]).ConvertAll<GridInstantMessage>((o) =>
                                                                                        {
                                                                                            GridInstantMessage im =
                                                                                                new GridInstantMessage();
                                                                                            im.FromOSD((OSDMap) o);
                                                                                            return im;
                                                                                        });
                ISceneManager manager = m_registry.RequestModuleInterface<ISceneManager>();
                if (manager != null)
                {
                    foreach (GridInstantMessage im in messages)
                    {
                        Framework.PresenceInfo.IScenePresence UserPresence;

                        foreach (IScene scene in manager.Scenes)
                        {
                            UserPresence = scene.GetScenePresence(im.ToAgentID);

                            //AR: Do not fire for child agents or group messages are sent for every region
                            if (UserPresence != null && UserPresence.IsChildAgent == false)
                            {
                                IMessageTransferModule messageTransfer = scene.RequestModuleInterface<IMessageTransferModule>();
                                if (messageTransfer != null)
                                {
                                    messageTransfer.SendInstantMessage(im);
                                }
                            }
                        }
                    }
                }
            }
            return null;
        }
        /// <summary>
        /// </summary>
        /// <param name="msg"></param>
        private void OnGridInstantMessage(GridInstantMessage msg)
        {
            byte dialog = msg.Dialog;

            if (dialog != (byte) InstantMessageDialog.MessageFromAgent
                && dialog != (byte) InstantMessageDialog.StartTyping
                && dialog != (byte) InstantMessageDialog.StopTyping
                && dialog != (byte) InstantMessageDialog.MessageFromObject)
            {
                return;
            }

            if (m_TransferModule != null)
            {
                UserAccount account = m_Scene.UserAccountService.GetUserAccount(m_Scene.RegionInfo.AllScopeIDs,
                                                                                msg.FromAgentID);
                if (account != null)
                    msg.FromAgentName = account.Name;
                else
                    msg.FromAgentName = msg.FromAgentName + "(No account found for this user)";

                IScenePresence presence = null;
                if (m_Scene.TryGetScenePresence(msg.ToAgentID, out presence))
                {
                    presence.ControllingClient.SendInstantMessage(msg);
                    return;
                }
            }
        }
        public virtual void SendInstantMessages(GridInstantMessage im, List<UUID> AgentsToSendTo)
        {
            //Check for local users first
            List<UUID> RemoveUsers = new List<UUID>();
            foreach (UUID t in AgentsToSendTo)
            {
                IScenePresence user;
                foreach (IScene scene in m_scenes)
                {
                    if (!RemoveUsers.Contains(t) &&
                        scene.TryGetScenePresence(t, out user))
                    {
                        // Local message
                        user.ControllingClient.SendInstantMessage(im);
                        RemoveUsers.Add(t);
                    }
                }
            }
            //Clear the local users out
            foreach (UUID agentID in RemoveUsers)
            {
                AgentsToSendTo.Remove(agentID);
            }

            SendMultipleGridInstantMessageViaXMLRPC(im, AgentsToSendTo);
        }
        public void OfflineFriendRequest(IClientAPI client)
        {
            // Barrowed a few lines from SendFriendsOnlineIfNeeded() above.
            UUID agentID = client.AgentId;
            FriendInfo[] friends = FriendsService.GetFriendsRequest(agentID).ToArray();
            GridInstantMessage im = new GridInstantMessage()
            {
                ToAgentID = agentID,
                Dialog = (byte)InstantMessageDialog.FriendshipOffered,
                Message = "Will you be my friend?",
                Offline = 1,
                RegionID = client.Scene.RegionInfo.RegionID
            };
            foreach (FriendInfo fi in friends)
            {
                if (fi.MyFlags == 0)
                {
                    UUID fromAgentID;
                    if (!UUID.TryParse(fi.Friend, out fromAgentID))
                        continue;

                    UserAccount account = m_scene.UserAccountService.GetUserAccount(
                        client.Scene.RegionInfo.AllScopeIDs, fromAgentID);
                    im.FromAgentID = fromAgentID;
                    if (account != null)
                        im.FromAgentName = account.Name;
                    im.Offline = 1;
                    im.SessionID = im.FromAgentID;

                    LocalFriendshipOffered(agentID, im);
                }
            }
        }
 protected OSDMap OnMessageReceived(OSDMap message)
 {
     if (!message.ContainsKey("Method"))
         return null;
     if (message["Method"] == "FriendGrantRights")
     {
         UUID Requester = message["Requester"].AsUUID();
         UUID Target = message["Target"].AsUUID();
         int MyFlags = message["MyFlags"].AsInteger();
         int Rights = message["Rights"].AsInteger();
         LocalGrantRights(Requester, Target, MyFlags, Rights);
     }
     else if (message["Method"] == "FriendTerminated")
     {
         UUID Requester = message["Requester"].AsUUID();
         UUID ExFriend = message["ExFriend"].AsUUID();
         LocalFriendshipTerminated(ExFriend, Requester);
     }
     else if (message["Method"] == "FriendshipOffered")
     {
         //UUID Requester = message["Requester"].AsUUID();
         UUID Friend = message["Friend"].AsUUID();
         GridInstantMessage im = new GridInstantMessage();
         im.FromOSD((OSDMap) message["Message"]);
         LocalFriendshipOffered(Friend, im);
     }
     else if (message["Method"] == "FriendshipDenied")
     {
         UUID Requester = message["Requester"].AsUUID();
         string ClientName = message["ClientName"].AsString();
         UUID FriendID = message["FriendID"].AsUUID();
         LocalFriendshipDenied(Requester, ClientName, FriendID);
     }
     else if (message["Method"] == "FriendshipApproved")
     {
         UUID Requester = message["Requester"].AsUUID();
         string ClientName = message["ClientName"].AsString();
         UUID FriendID = message["FriendID"].AsUUID();
         LocalFriendshipApproved(Requester, ClientName, null, FriendID);
     }
     return null;
 }
        public bool LocalFriendshipDenied(UUID userID, string userName, UUID friendID)
        {
            IClientAPI friendClient = LocateClientObject(friendID);
            if (friendClient != null)
            {
                // the prospective friend in this sim as root agent
                GridInstantMessage im = new GridInstantMessage()
                {
                    FromAgentID = userID,
                    FromAgentName = userName,
                    ToAgentID = friendID,
                    Dialog = (byte)InstantMessageDialog.FriendshipDeclined,
                    Message = userID.ToString(),
                    Offline = 0,
                    RegionID = friendClient.Scene.RegionInfo.RegionID
                };
                friendClient.SendInstantMessage(im);
                // we're done
                return true;
            }

            return false;
        }
 public bool LocalFriendshipOffered(UUID toID, GridInstantMessage im)
 {
     IClientAPI friendClient = LocateClientObject(toID);
     if (friendClient != null)
     {
         // the prospective friend in this sim as root agent
         friendClient.SendInstantMessage(im);
         // we're done
         return true;
     }
     return false;
 }
        public bool LocalFriendshipApproved(UUID userID, string name, IClientAPI us, UUID friendID)
        {
            IClientAPI friendClient = LocateClientObject(friendID);
            if (friendClient != null)
            {
                //They are online, send the online message
                if (us != null)
                    us.SendAgentOnline(new[] {friendID});

                // the prospective friend in this sim as root agent
                GridInstantMessage im = new GridInstantMessage()
                {
                    FromAgentID = userID,
                    FromAgentName = name,
                    ToAgentID = friendID,
                    Dialog = (byte)InstantMessageDialog.FriendshipAccepted,
                    Message = userID.ToString(),
                    Offline = 0,
                    RegionID = us.Scene.RegionInfo.RegionID
                };
                friendClient.SendInstantMessage(im);

                // Update the local cache
                UpdateFriendsCache(friendID);

                //
                // put a calling card into the inventory of the friend
                //
                ICallingCardModule ccmodule = friendClient.Scene.RequestModuleInterface<ICallingCardModule>();
                if (ccmodule != null)
                {
                    UserAccount account = friendClient.Scene.UserAccountService.GetUserAccount(friendClient.AllScopeIDs,
                                                                                               userID);
                    UUID folderID =
                        friendClient.Scene.InventoryService.GetFolderForType(friendID, InventoryType.Unknown,
                                                                             AssetType.CallingCard).ID;
                    ccmodule.CreateCallingCard(friendClient, userID, folderID, account.Name);
                }
                // we're done
                return true;
            }

            return false;
        }
        private void UndeliveredMessage(GridInstantMessage im, string reason)
        {
            if (OfflineMessagesConnector == null || im == null)
                return;
            IClientAPI client = FindClient(im.FromAgentID);
            if ((client == null) && (im.Dialog != 32))
                return;
            if (!OfflineMessagesConnector.AddOfflineMessage(im))
            {
                if ((!im.FromGroup) && (reason != "User does not exist.") && (client != null))
                    client.SendInstantMessage(new GridInstantMessage()
                    {
                        FromAgentID = im.ToAgentID,
                        FromAgentName = "System",
                        ToAgentID = im.FromAgentID,
                        Dialog = (byte)InstantMessageDialog.MessageFromAgent,
                        Message = "User has too many IMs already, please try again later.",
                        Offline = 0,
                        RegionID = im.RegionID
                    });
                else if (client == null)
                    return;
            }
            else if ((im.Offline != 0)
                     && (!im.FromGroup || im.FromGroup))
            {
                if (im.Dialog == 32) //Group notice
                {
                    IGroupsModule module = m_Scene.RequestModuleInterface<IGroupsModule>();
                    if (module != null)
                        im = module.BuildOfflineGroupNotice(im);
                    return;
                }
                if (client == null) return;
                IEmailModule emailModule = m_Scene.RequestModuleInterface<IEmailModule>();
                if (emailModule != null && m_SendOfflineMessagesToEmail)
                {
                    IUserProfileInfo profile =
                        Framework.Utilities.DataManager.RequestPlugin<IProfileConnector>().GetUserProfile(im.ToAgentID);
                    if (profile != null && profile.IMViaEmail)
                    {
                        UserAccount account = m_Scene.UserAccountService.GetUserAccount(null, im.ToAgentID);
                        if (account != null && !string.IsNullOrEmpty(account.Email))
                        {
                            emailModule.SendEmail(UUID.Zero, account.Email,
                                                  string.Format("Offline Message from {0}", im.FromAgentName),
                                                  string.Format("Time: {0}\n",
                                                                Util.ToDateTime(im.Timestamp).ToShortDateString()) +
                                                  string.Format("From: {0}\n", im.FromAgentName) +
                                                  string.Format("Message: {0}\n", im.Message), m_Scene);
                        }
                    }
                }

                if (im.Dialog == (byte) InstantMessageDialog.MessageFromAgent && !im.FromGroup)
                {
                    client.SendInstantMessage(new GridInstantMessage()
                    {
                        FromAgentID = im.ToAgentID,
                        FromAgentName = "System",
                        ToAgentID = im.FromAgentID,
                        Dialog = (byte)InstantMessageDialog.MessageFromAgent,
                        Message = "Message saved, reason: " + reason,
                        Offline = 0,
                        RegionID = im.RegionID
                    });
                }

                if (im.Dialog == (byte) InstantMessageDialog.InventoryOffered)
                    client.SendAlertMessage("User is not online. Inventory has been saved");
            }
            else if (im.Offline == 0)
            {
                if (client == null) return;
                if (im.Dialog == (byte) InstantMessageDialog.MessageFromAgent && !im.FromGroup)
                {
                    client.SendInstantMessage(new GridInstantMessage()
                    {
                        FromAgentID = im.ToAgentID,
                        FromAgentName = "System",
                        ToAgentID = im.FromAgentID,
                        Dialog = (byte)InstantMessageDialog.MessageFromAgent,
                        Message = "Message saved, reason: " + reason,
                        Offline = 0,
                        RegionID = im.RegionID
                    });
                }

                if (im.Dialog == (byte) InstantMessageDialog.InventoryOffered)
                    client.SendAlertMessage("User not able to be found. Inventory has been saved");
            }
        }
 public void TriggerIncomingInstantMessage(GridInstantMessage message)
 {
     IncomingInstantMessage handlerIncomingInstantMessage = OnIncomingInstantMessage;
     if (handlerIncomingInstantMessage != null)
     {
         foreach (IncomingInstantMessage d in handlerIncomingInstantMessage.GetInvocationList())
         {
             try
             {
                 d(message);
             }
             catch (Exception e)
             {
                 MainConsole.Instance.ErrorFormat(
                     "[EVENT MANAGER]: Delegate for TriggerIncomingInstantMessage failed - continuing.  {0} {1}",
                     e, e.StackTrace);
             }
         }
     }
 }
        public DateTime llInstantMessage(string user, string message)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
                return DateTime.Now;

            // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
            // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
            // but I don't think we have a list of scenes available from here.
            // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)

            UUID friendTransactionID = UUID.Random();

            GridInstantMessage msg = new GridInstantMessage
                                         {
                                             FromAgentID = m_host.UUID,
                                             ToAgentID = UUID.Parse(user),
                                             SessionID = friendTransactionID,
                                             FromAgentName = m_host.Name,
                                             RegionID = m_host.ParentEntity.Scene.RegionInfo.RegionID
                                         };

            // This is the item we're mucking with here

            // Cap the message length at 1024.
            if (message != null && message.Length > 1024)
                msg.Message = message.Substring(0, 1024);
            else
                msg.Message = message;

            msg.Dialog = (byte) InstantMessageDialog.MessageFromObject;
            msg.FromGroup = false;
            msg.Offline = 0;
            msg.ParentEstateID = 0;
            msg.Position = m_host.AbsolutePosition;
            msg.RegionID = World.RegionInfo.RegionID;
            msg.BinaryBucket
                = Util.StringToBytes256(
                    "{0}/{1}/{2}/{3}",
                    World.RegionInfo.RegionName,
                    (int) Math.Floor(m_host.AbsolutePosition.X),
                    (int) Math.Floor(m_host.AbsolutePosition.Y),
                    (int) Math.Floor(m_host.AbsolutePosition.Z));

            if (m_TransferModule != null)
            {
                m_TransferModule.SendInstantMessage(msg);
            }
            return PScriptSleep(2000);
        }
        private void ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im)
        {
            // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID)
            // We stick this agent's ID as imSession, so that it's directly available on the receiving end
            im.SessionID = im.FromAgentID;

            // Try the local sim
            UserAccount account = UserAccountService.GetUserAccount(m_scene.RegionInfo.AllScopeIDs, agentID);
            im.FromAgentName = (account == null) ? "Unknown" : account.Name;

            if (LocalFriendshipOffered(friendID, im))
                return;

            // The prospective friend is not here [as root]. Let's4 forward.
            SyncMessagePosterService.PostToServer(SyncMessageHelper.FriendshipOffered(agentID, friendID, im,
                                                                                      m_scene.RegionInfo.RegionID));
            // If the prospective friend is not online, he'll get the message upon login.
        }
        public void OnInstantMessage(IClientAPI client, GridInstantMessage im)
        {
            byte dialog = im.Dialog;

            if (dialog != (byte) InstantMessageDialog.MessageFromAgent
                && dialog != (byte) InstantMessageDialog.StartTyping
                && dialog != (byte) InstantMessageDialog.StopTyping
                && dialog != (byte) InstantMessageDialog.BusyAutoResponse
                && dialog != (byte) InstantMessageDialog.MessageFromObject)
            {
                return;
            }

            if (m_TransferModule != null)
            {
                if (client == null)
                {
                    UserAccount account = m_Scene.UserAccountService.GetUserAccount(m_Scene.RegionInfo.AllScopeIDs,
                                                                                    im.FromAgentID);
                    if (account != null)
                        im.FromAgentName = account.Name;
                    else
                        im.FromAgentName = im.FromAgentName + "(No account found for this user)";
                }
                else
                    im.FromAgentName = client.Name;

                m_TransferModule.SendInstantMessage(im);
            }
        }
        private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
        {
            if ((InstantMessageDialog) im.Dialog == InstantMessageDialog.FriendshipOffered)
            {
                // we got a friendship offer
                UUID principalID = im.FromAgentID;
                UUID friendID = im.ToAgentID;

                //Can't trust the incoming name for friend offers, so we have to find it ourselves.
                UserAccount sender = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.AllScopeIDs,
                                                                               principalID);
                im.FromAgentName = sender.Name;
                UserAccount reciever = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.AllScopeIDs,
                                                                                 friendID);

                MainConsole.Instance.DebugFormat("[FRIENDS]: {0} offered friendship to {1}", sender.Name, reciever.Name);
                // This user wants to be friends with the other user.
                // Let's add the relation backwards, in case the other is not online
                FriendsService.StoreFriend(friendID, principalID.ToString(), 0);

                // Now let's ask the other user to be friends with this user
                ForwardFriendshipOffer(principalID, friendID, im);
            }
        }
        public virtual void SendInstantMessage(GridInstantMessage im)
        {
            UUID toAgentID = im.ToAgentID;

            //Look locally first
            IScenePresence user;
            foreach (IScene scene in m_scenes)
            {
                if (scene.TryGetScenePresence(toAgentID, out user))
                {
                    user.ControllingClient.SendInstantMessage(im);
                    return;
                }
            }
            ISceneChildEntity childPrim = null;
            foreach (IScene scene in m_scenes)
            {
                if ((childPrim = scene.GetSceneObjectPart(toAgentID)) != null)
                {
                    im.ToAgentID = childPrim.OwnerID;
                    SendInstantMessage(im);
                    return;
                }
            }
            //MainConsole.Instance.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
            SendGridInstantMessageViaXMLRPC(im);
        }
        protected virtual void SendMultipleGridInstantMessageViaXMLRPC(GridInstantMessage im, List<UUID> users)
        {
            Dictionary<UUID, string> HTTPPaths = new Dictionary<UUID, string>();

            foreach (UUID agentID in users)
            {
                lock (IMUsersCache)
                {
                    string HTTPPath = "";
                    if (!IMUsersCache.TryGetValue(agentID, out HTTPPath))
                        HTTPPath = "";
                    else
                        HTTPPaths.Add(agentID, HTTPPath);
                }
            }
            List<UUID> CompletedUsers = new List<UUID>();
            foreach (KeyValuePair<UUID, string> kvp in HTTPPaths)
            {
                //Fix the agentID
                im.ToAgentID = kvp.Key;
                //We've tried to send an IM to them before, pull out their info
                //Send the IM to their last location
                if (!doIMSending(kvp.Value, im))
                {
                    //If this fails, the user has either moved from their stored location or logged out
                    //Since it failed, let it look them up again and rerun
                    lock (IMUsersCache)
                    {
                        IMUsersCache.Remove(kvp.Key);
                    }
                }
                else
                {
                    //Send the IM, and it made it to the user, return true
                    CompletedUsers.Add(kvp.Key);
                }
            }

            //Remove the finished users
            foreach (UUID agentID in CompletedUsers)
            {
                users.Remove(agentID);
            }
            HTTPPaths.Clear();

            //Now query the grid server for the agents
            List<string> Queries = users.Select(agentID => agentID.ToString()).ToList();

            if (Queries.Count == 0)
                return; //All done

            //Ask for the user new style first
            List<string> AgentLocations = m_agentInfoService.GetAgentsLocations(im.FromAgentID.ToString(),
                                                                                       Queries);
            //If this is false, this doesn't exist on the presence server and we use the legacy way
            if (AgentLocations.Count != 0)
            {
                for (int i = 0; i < users.Count; i++)
                {
                    //No agents, so this user is offline
                    if (AgentLocations[i] == "NotOnline")
                    {
                        IMUsersCache.Remove(users[i]);
                        MainConsole.Instance.Debug("[GRID INSTANT MESSAGE]: Unable to deliver an instant message to " +
                                                   users[i] +
                                                   ", user was not online");
                        im.ToAgentID = users[i];
                        HandleUndeliveredMessage(im, "User is not set as online by presence service.");
                        continue;
                    }
                    if (AgentLocations[i] == "NonExistant")
                    {
                        IMUsersCache.Remove(users[i]);
                        MainConsole.Instance.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message to " +
                                                  users[i] +
                                                  ", user does not exist");
                        im.ToAgentID = users[i];
                        HandleUndeliveredMessage(im, "User does not exist.");
                        continue;
                    }
                    HTTPPaths.Add(users[i], AgentLocations[i]);
                }
            }
            else
            {
                MainConsole.Instance.Info(
                    "[GRID INSTANT MESSAGE]: Unable to deliver an instant message, no users found.");
                return;
            }

            //We found the agent's location, now ask them about the user
            foreach (KeyValuePair<UUID, string> kvp in HTTPPaths)
            {
                if (kvp.Value != "")
                {
                    im.ToAgentID = kvp.Key;
                    if (!doIMSending(kvp.Value, im))
                    {
                        //It failed
                        lock (IMUsersCache)
                        {
                            //Remove them so we keep testing against the db
                            IMUsersCache.Remove(kvp.Key);
                        }
                        HandleUndeliveredMessage(im, "Failed to send IM to destination.");
                    }
                    else
                    {
                        //Add to the cache
                        if (!IMUsersCache.ContainsKey(kvp.Key))
                            IMUsersCache.Add(kvp.Key, kvp.Value);
                        //Send the IM, and it made it to the user, return true
                        continue;
                    }
                }
                else
                {
                    lock (IMUsersCache)
                    {
                        //Remove them so we keep testing against the db
                        IMUsersCache.Remove(kvp.Key);
                    }
                    HandleUndeliveredMessage(im, "Agent Location was blank.");
                }
            }
        }
 /// <summary>
 ///     This actually does the XMLRPC Request
 /// </summary>
 /// <param name="httpInfo">RegionInfo we pull the data out of to send the request to</param>
 /// <param name="xmlrpcdata">The Instant Message data Hashtable</param>
 /// <returns>Bool if the message was successfully delivered at the other side.</returns>
 protected virtual bool doIMSending(string httpInfo, GridInstantMessage message)
 {
     MemoryStream stream = new MemoryStream();
     ProtoBuf.Serializer.Serialize(stream, message);
     byte[] data = WebUtils.PostToService(httpInfo + "/gridinstantmessages/", stream.ToArray());
     return data == null || data.Length == 0 || data[0] == 0 ? false : true;
 }
        public static OSDMap FriendshipOffered(UUID requester, UUID friend, GridInstantMessage im,
                                               UUID requestingRegion)
        {
            OSDMap llsdBody = new OSDMap
                                  {
                                      {"Requester", requester},
                                      {"Friend", friend},
                                      {"IM", im.ToOSD()},
                                      {"RequestingRegion", requestingRegion}
                                  };

            return buildEvent("FriendshipOffered", llsdBody, requester, requestingRegion);
        }
        /// <summary>
        ///     Recursive SendGridInstantMessage over XMLRPC method.
        ///     This is called from within a dedicated thread.
        ///     The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from
        ///     itself, prevRegionHandle will be the last region handle that we tried to send.
        ///     If the handles are the same, we look up the user's location using the grid.
        ///     If the handles are still the same, we end.  The send failed.
        /// </summary>
        /// <param name="im"></param>
        /// <param name="prevRegion">
        ///     Pass in 0 the first time this method is called.  It will be called recursively with the last
        ///     regionhandle tried
        /// </param>
        protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im,
                                                                    GridRegion prevRegion)
        {
            UUID toAgentID = im.ToAgentID;
            string HTTPPath = "";

            lock (IMUsersCache)
            {
                if (!IMUsersCache.TryGetValue(toAgentID, out HTTPPath))
                    HTTPPath = "";
            }

            if (HTTPPath != "")
            {
                //We've tried to send an IM to them before, pull out their info
                //Send the IM to their last location
                if (!doIMSending(HTTPPath, im))
                {
                    //If this fails, the user has either moved from their stored location or logged out
                    //Since it failed, let it look them up again and rerun
                    lock (IMUsersCache)
                    {
                        IMUsersCache.Remove(toAgentID);
                    }
                    //Clear the path and let it continue trying again.
                    HTTPPath = "";
                }
                else
                {
                    //Send the IM, and it made it to the user, return true
                    return;
                }
            }

            //Now query the grid server for the agent
            List<string> AgentLocations = m_agentInfoService.GetAgentsLocations(im.FromAgentID.ToString(),
                                                                 new List<string>(new[] {toAgentID.ToString()}));
            if (AgentLocations.Count > 0)
            {
                //No agents, so this user is offline
                if (AgentLocations[0] == "NotOnline")
                {
                    lock (IMUsersCache)
                    {
                        //Remove them so we keep testing against the db
                        IMUsersCache.Remove(toAgentID);
                    }
                    MainConsole.Instance.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
                    HandleUndeliveredMessage(im, "User is not set as online by presence service.");
                    return;
                }
                if (AgentLocations[0] == "NonExistant")
                {
                    IMUsersCache.Remove(toAgentID);
                    MainConsole.Instance.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message to " +
                                              toAgentID +
                                              ", user does not exist");
                    HandleUndeliveredMessage(im, "User does not exist.");
                    return;
                }
                HTTPPath = AgentLocations[0];
            }

            //We found the agent's location, now ask them about the user
            if (HTTPPath != "")
            {
                if (!doIMSending(HTTPPath, im))
                {
                    //It failed, stop now
                    lock (IMUsersCache)
                    {
                        //Remove them so we keep testing against the db
                        IMUsersCache.Remove(toAgentID);
                    }
                    MainConsole.Instance.Info(
                        "[GRID INSTANT MESSAGE]: Unable to deliver an instant message as the region could not be found");
                    HandleUndeliveredMessage(im, "Failed to send IM to destination.");
                    return;
                }
                else
                {
                    //Add to the cache
                    if (!IMUsersCache.ContainsKey(toAgentID))
                        IMUsersCache.Add(toAgentID, HTTPPath);
                    //Send the IM, and it made it to the user, return true
                    return;
                }
            }
            else
            {
                //Couldn't find them, stop for now
                lock (IMUsersCache)
                {
                    //Remove them so we keep testing against the db
                    IMUsersCache.Remove(toAgentID);
                }
                MainConsole.Instance.Info(
                    "[GRID INSTANT MESSAGE]: Unable to deliver an instant message as the region could not be found");
                HandleUndeliveredMessage(im, "Agent Location was blank.");
            }
        }
        public void SendChatToSession(UUID agentID, GridInstantMessage im)
        {
            if (m_doRemoteOnly)
            {
                DoRemoteCallPost(true, "InstantMessageServerURI", agentID, im);
                return;
            }

            Util.FireAndForget((o) =>
                                   {
                                       ChatSession session;
                                       ChatSessions.TryGetValue(im.SessionID, out session);
                                       if (session == null)
                                           return;

                                       if (agentID != UUID.Zero) //Not system
                                       {
                                           ChatSessionMember sender = FindMember(im.SessionID, agentID);
                                           if (sender.MuteText)
                                               return; //They have been admin muted, don't allow them to send anything
                                       }

                                       Dictionary<string, List<GridInstantMessage>> messagesToSend =
                                           new Dictionary<string, List<GridInstantMessage>>();
                                       foreach (ChatSessionMember member in session.Members)
                                       {
                                           if (member.HasBeenAdded)
                                           {
                                               im.ToAgentID = member.AvatarKey;
                                               im.BinaryBucket = Utils.StringToBytes(session.Name);
                                               im.RegionID = UUID.Zero;
                                               im.ParentEstateID = 0;
                                               im.Offline = 0;
                                               GridInstantMessage message = new GridInstantMessage();
                                               message.FromOSD(im.ToOSD());
                                               //im.timestamp = 0;
                                               string uri = FindRegionURI(member.AvatarKey);
                                               if (uri != "") //Check if they are online
                                               {
                                                   //Bulk send all of the instant messages to the same region, so that we don't send them one-by-one over and over
                                                   if (messagesToSend.ContainsKey(uri))
                                                       messagesToSend[uri].Add(message);
                                                   else
                                                       messagesToSend.Add(uri, new List<GridInstantMessage>() {message});
                                               }
                                           }
                                           else if (!member.RequestedRemoval)
                                               //If they're requested to leave, don't recontact them
                                           {
                                               UUID regionID = FindRegionID(member.AvatarKey);
                                               if (regionID != UUID.Zero)
                                               {
                                                   im.ToAgentID = member.AvatarKey;
                                                   m_eventQueueService.ChatterboxInvitation(
                                                       session.SessionID
                                                       , session.Name
                                                       , im.FromAgentID
                                                       , im.Message
                                                       , im.ToAgentID
                                                       , im.FromAgentName
                                                       , im.Dialog
                                                       , im.Timestamp
                                                       , im.Offline == 1
                                                       , (int) im.ParentEstateID
                                                       , im.Position
                                                       , 1
                                                       , im.SessionID
                                                       , false
                                                       , Utils.StringToBytes(session.Name)
                                                       , regionID
                                                       );
                                               }
                                           }
                                       }
                                       foreach (KeyValuePair<string, List<GridInstantMessage>> kvp in messagesToSend)
                                       {
                                           SendInstantMessages(kvp.Key, kvp.Value);
                                       }
                                   });
        }
        private void HandleUndeliveredMessage(GridInstantMessage im, string reason)
        {
            UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;

            // If this event has handlers, then an IM from an agent will be
            // considered delivered. This will suppress the error message.
            //
            if (handlerUndeliveredMessage != null)
            {
                handlerUndeliveredMessage(im, reason);
                return;
            }

            //MainConsole.Instance.DebugFormat("[INSTANT MESSAGE]: Undeliverable");
        }
 public void SendInstantMessage(GridInstantMessage im)
 {
     IMessageTransferModule m_TransferModule =
         m_object.Scene.RequestModuleInterface<IMessageTransferModule>();
     if (m_TransferModule != null)
         m_TransferModule.SendInstantMessage(im);
 }
 /// <summary>
 ///     If its a message we deal with, pull it from the client here
 /// </summary>
 /// <param name="client"></param>
 /// <param name="im"></param>
 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
 {
     byte dialog = im.Dialog;
     switch (dialog)
     {
         case (byte) InstantMessageDialog.SessionGroupStart:
             m_imService.CreateGroupChat(client.AgentId, im);
             break;
         case (byte) InstantMessageDialog.SessionSend:
             m_imService.SendChatToSession(client.AgentId, im);
             break;
         case (byte) InstantMessageDialog.SessionDrop:
             m_imService.DropMemberFromSession(client.AgentId, im);
             break;
     }
 }
        public void CreateGroupChat(UUID AgentID, GridInstantMessage im)
        {
            if (m_doRemoteOnly)
            {
                DoRemoteCallPost(true, "InstantMessageServerURI", AgentID, im);
                return;
            }

            UUID GroupID = im.SessionID;

            GroupRecord groupInfo = m_groupData.GetGroupRecord(AgentID, GroupID, null);

            if (groupInfo != null)
            {
                if (!GroupPermissionCheck(AgentID, GroupID, GroupPowers.JoinChat))
                    return; //They have to be able to join to create a group chat
                //Create the session.
                if (!SessionExists(GroupID))
                {
                    CreateSession(new ChatSession
                                      {
                                          Members = new List<ChatSessionMember>(),
                                          SessionID = GroupID,
                                          Name = groupInfo.GroupName
                                      });
                    AddMemberToGroup(new ChatSessionMember
                                         {
                                             AvatarKey = AgentID,
                                             CanVoiceChat = false,
                                             IsModerator =
                                                 GroupPermissionCheck(AgentID, GroupID, GroupPowers.ModerateChat),
                                             MuteText = false,
                                             MuteVoice = false,
                                             HasBeenAdded = true
                                         }, GroupID);

                    foreach (
                        GroupMembersData gmd in
                            m_groupData.GetGroupMembers(AgentID, GroupID)
                                       .Where(gmd => gmd.AgentID != AgentID)
                                       .Where(
                                           gmd =>
                                           (gmd.AgentPowers & (ulong) GroupPowers.JoinChat) ==
                                           (ulong) GroupPowers.JoinChat))
                    {
                        AddMemberToGroup(new ChatSessionMember
                                             {
                                                 AvatarKey = gmd.AgentID,
                                                 CanVoiceChat = false,
                                                 IsModerator =
                                                     GroupPermissionCheck(gmd.AgentID, GroupID, GroupPowers.ModerateChat),
                                                 MuteText = false,
                                                 MuteVoice = false,
                                                 HasBeenAdded = false
                                             }, GroupID);
                    }
                    //Tell us that it was made successfully
                    m_eventQueueService.ChatterBoxSessionStartReply(groupInfo.GroupName, GroupID,
                                                                    AgentID, FindRegionID(AgentID));
                }
                else
                {
                    ChatSession thisSession = GetSession(GroupID);
                    //A session already exists
                    //Add us
                    AddMemberToGroup(new ChatSessionMember
                                         {
                                             AvatarKey = AgentID,
                                             CanVoiceChat = false,
                                             IsModerator =
                                                 GroupPermissionCheck(AgentID, GroupID, GroupPowers.ModerateChat),
                                             MuteText = false,
                                             MuteVoice = false,
                                             HasBeenAdded = true
                                         }, GroupID);

                    //Tell us that we entered successfully
                    m_eventQueueService.ChatterBoxSessionStartReply(groupInfo.GroupName, GroupID,
                                                                    AgentID, FindRegionID(AgentID));
                    List<ChatterBoxSessionAgentListUpdatesMessage.AgentUpdatesBlock> Us =
                        new List<ChatterBoxSessionAgentListUpdatesMessage.AgentUpdatesBlock>();
                    List<ChatterBoxSessionAgentListUpdatesMessage.AgentUpdatesBlock> NotUsAgents =
                        new List<ChatterBoxSessionAgentListUpdatesMessage.AgentUpdatesBlock>();

                    foreach (ChatSessionMember sessionMember in thisSession.Members)
                    {
                        ChatterBoxSessionAgentListUpdatesMessage.AgentUpdatesBlock block =
                            new ChatterBoxSessionAgentListUpdatesMessage.AgentUpdatesBlock
                                {
                                    AgentID = sessionMember.AvatarKey,
                                    CanVoiceChat = sessionMember.CanVoiceChat,
                                    IsModerator = sessionMember.IsModerator,
                                    MuteText = sessionMember.MuteText,
                                    MuteVoice = sessionMember.MuteVoice,
                                    Transition = "ENTER"
                                };
                        if (AgentID == sessionMember.AvatarKey)
                            Us.Add(block);
                        if (sessionMember.HasBeenAdded)
                            // Don't add not joined yet agents. They don't want to be here.
                            NotUsAgents.Add(block);
                    }
                    foreach (ChatSessionMember member in thisSession.Members)
                    {
                        if (member.HasBeenAdded) //Only send to those in the group
                        {
                            UUID regionID = FindRegionID(member.AvatarKey);
                            if (regionID != UUID.Zero)
                            {
                                if (member.AvatarKey == AgentID)
                                {
                                    //Tell 'us' about all the other agents in the group
                                    m_eventQueueService.ChatterBoxSessionAgentListUpdates(GroupID, NotUsAgents.ToArray(),
                                                                                          member.AvatarKey,
                                                                                          "ENTER", regionID);
                                }
                                else
                                {
                                    //Tell 'other' agents about the new agent ('us')
                                    m_eventQueueService.ChatterBoxSessionAgentListUpdates(GroupID, Us.ToArray(),
                                                                                          member.AvatarKey,
                                                                                          "ENTER", regionID);
                                }
                            }
                        }
                    }
                }

                ChatSessionMember agentMember = FindMember(GroupID, AgentID);

                //Tell us that we entered
                ChatterBoxSessionAgentListUpdatesMessage.AgentUpdatesBlock ourblock =
                    new ChatterBoxSessionAgentListUpdatesMessage.AgentUpdatesBlock
                        {
                            AgentID = AgentID,
                            CanVoiceChat = agentMember.CanVoiceChat,
                            IsModerator = agentMember.IsModerator,
                            MuteText = agentMember.MuteText,
                            MuteVoice = agentMember.MuteVoice,
                            Transition = "ENTER"
                        };
                m_eventQueueService.ChatterBoxSessionAgentListUpdates(GroupID, new[] {ourblock}, AgentID, "ENTER",
                                                                      FindRegionID(AgentID));
            }
        }