PageRenderTime 30ms CodeModel.GetById 22ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/Aurora/Modules/Avatar/AuroraChat/AuroraOfflineMessagesModule.cs

https://bitbucket.org/VirtualReality/software-testing
C# | 273 lines | 212 code | 29 blank | 32 comment | 73 complexity | 9b5f4c550c86584d3eca86da7f9ae451 MD5 | raw file
  1/*
  2 * Copyright (c) Contributors, http://aurora-sim.org/
  3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4 *
  5 * Redistribution and use in source and binary forms, with or without
  6 * modification, are permitted provided that the following conditions are met:
  7 *     * Redistributions of source code must retain the above copyright
  8 *       notice, this list of conditions and the following disclaimer.
  9 *     * Redistributions in binary form must reproduce the above copyright
 10 *       notice, this list of conditions and the following disclaimer in the
 11 *       documentation and/or other materials provided with the distribution.
 12 *     * Neither the name of the Aurora-Sim Project nor the
 13 *       names of its contributors may be used to endorse or promote products
 14 *       derived from this software without specific prior written permission.
 15 *
 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 26 */
 27
 28using Aurora.Framework;
 29using Aurora.Framework.ClientInterfaces;
 30using Aurora.Framework.ConsoleFramework;
 31using Aurora.Framework.DatabaseInterfaces;
 32using Aurora.Framework.Modules;
 33using Aurora.Framework.PresenceInfo;
 34using Aurora.Framework.SceneInfo;
 35using Aurora.Framework.Services;
 36using Aurora.Framework.Services.ClassHelpers.Profile;
 37using Aurora.Framework.Utilities;
 38using Nini.Config;
 39using OpenMetaverse;
 40using System;
 41using System.Collections.Generic;
 42
 43namespace Aurora.Modules.Chat
 44{
 45    public class AuroraOfflineMessageModule : INonSharedRegionModule
 46    {
 47        private bool enabled = true;
 48        private IScene m_Scene;
 49        private IMessageTransferModule m_TransferModule = null;
 50        private IOfflineMessagesConnector OfflineMessagesConnector;
 51        private bool m_SendOfflineMessagesToEmail = false;
 52
 53        private Dictionary<UUID, List<GridInstantMessage>> m_offlineMessagesCache =
 54            new Dictionary<UUID, List<GridInstantMessage>>();
 55
 56        public void Initialise(IConfigSource config)
 57        {
 58            IConfig cnf = config.Configs["Messaging"];
 59            if (cnf == null)
 60            {
 61                enabled = false;
 62                return;
 63            }
 64            if (cnf.GetString("OfflineMessageModule", "AuroraOfflineMessageModule") !=
 65                "AuroraOfflineMessageModule")
 66            {
 67                enabled = false;
 68                return;
 69            }
 70
 71            m_SendOfflineMessagesToEmail = cnf.GetBoolean("SendOfflineMessagesToEmail", m_SendOfflineMessagesToEmail);
 72        }
 73
 74        public void AddRegion(IScene scene)
 75        {
 76            if (!enabled)
 77                return;
 78
 79            m_Scene = scene;
 80
 81            scene.EventManager.OnNewClient += OnNewClient;
 82            scene.EventManager.OnClosingClient += OnClosingClient;
 83            scene.EventManager.OnCachedUserInfo += UpdateCachedInfo;
 84        }
 85
 86        public void RegionLoaded(IScene scene)
 87        {
 88            if (!enabled)
 89                return;
 90
 91            if (m_TransferModule == null)
 92            {
 93                OfflineMessagesConnector = Framework.Utilities.DataManager.RequestPlugin<IOfflineMessagesConnector>();
 94                m_TransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
 95                if (m_TransferModule == null || OfflineMessagesConnector == null)
 96                {
 97                    scene.EventManager.OnNewClient -= OnNewClient;
 98                    scene.EventManager.OnClosingClient -= OnClosingClient;
 99
100                    enabled = false;
101                    m_Scene = null;
102
103                    MainConsole.Instance.Error(
104                        "[OFFLINE MESSAGING] No message transfer module or OfflineMessagesConnector is enabled. Diabling offline messages");
105                    return;
106                }
107                m_TransferModule.OnUndeliveredMessage += UndeliveredMessage;
108            }
109        }
110
111        public void RemoveRegion(IScene scene)
112        {
113            if (!enabled)
114                return;
115
116            m_Scene = null;
117
118            if (m_TransferModule != null)
119            {
120                scene.EventManager.OnNewClient -= OnNewClient;
121                scene.EventManager.OnClosingClient -= OnClosingClient;
122                scene.EventManager.OnCachedUserInfo -= UpdateCachedInfo;
123                m_TransferModule.OnUndeliveredMessage -= UndeliveredMessage;
124            }
125        }
126
127        public string Name
128        {
129            get { return "AuroraOfflineMessageModule"; }
130        }
131
132        public Type ReplaceableInterface
133        {
134            get { return null; }
135        }
136
137        public void Close()
138        {
139        }
140
141        private IClientAPI FindClient(UUID agentID)
142        {
143            IScenePresence presence = m_Scene.GetScenePresence(agentID);
144            return (presence != null && !presence.IsChildAgent) ? presence.ControllingClient : null;
145        }
146
147        private void UpdateCachedInfo(UUID agentID, CachedUserInfo info)
148        {
149            lock (m_offlineMessagesCache)
150                m_offlineMessagesCache[agentID] = info.OfflineMessages;
151        }
152
153        private void OnNewClient(IClientAPI client)
154        {
155            client.OnRetrieveInstantMessages += RetrieveInstantMessages;
156        }
157
158        private void OnClosingClient(IClientAPI client)
159        {
160            client.OnRetrieveInstantMessages -= RetrieveInstantMessages;
161        }
162
163        private void RetrieveInstantMessages(IClientAPI client)
164        {
165            if (OfflineMessagesConnector == null)
166                return;
167
168            List<GridInstantMessage> msglist;
169            lock (m_offlineMessagesCache)
170            {
171                if (m_offlineMessagesCache.TryGetValue(client.AgentId, out msglist))
172                    m_offlineMessagesCache.Remove(client.AgentId);
173            }
174
175            if (msglist == null)
176                msglist = OfflineMessagesConnector.GetOfflineMessages(client.AgentId);
177            msglist.Sort(
178                delegate(GridInstantMessage a, GridInstantMessage b) { return a.timestamp.CompareTo(b.timestamp); });
179            foreach (GridInstantMessage IM in msglist)
180            {
181                // Send through scene event manager so all modules get a chance
182                // to look at this message before it gets delivered.
183                //
184                // Needed for proper state management for stored group
185                // invitations
186                //
187                IM.offline = 1;
188                m_Scene.EventManager.TriggerIncomingInstantMessage(IM);
189            }
190        }
191
192        private void UndeliveredMessage(GridInstantMessage im, string reason)
193        {
194            if (OfflineMessagesConnector == null || im == null)
195                return;
196            IClientAPI client = FindClient(im.fromAgentID);
197            if ((client == null) && (im.dialog != 32))
198                return;
199            if (!OfflineMessagesConnector.AddOfflineMessage(im))
200            {
201                if ((!im.fromGroup) && (reason != "User does not exist.") && (client != null))
202                    client.SendInstantMessage(new GridInstantMessage(
203                                                  null, im.toAgentID,
204                                                  "System", im.fromAgentID,
205                                                  (byte) InstantMessageDialog.MessageFromAgent,
206                                                  "User has too many IMs already, please try again later.",
207                                                  false, Vector3.Zero));
208                else if (client == null)
209                    return;
210            }
211            else if ((im.offline != 0)
212                     && (!im.fromGroup || im.fromGroup))
213            {
214                if (im.dialog == 32) //Group notice
215                {
216                    IGroupsModule module = m_Scene.RequestModuleInterface<IGroupsModule>();
217                    if (module != null)
218                        im = module.BuildOfflineGroupNotice(im);
219                    return;
220                }
221                if (client == null) return;
222                IEmailModule emailModule = m_Scene.RequestModuleInterface<IEmailModule>();
223                if (emailModule != null && m_SendOfflineMessagesToEmail)
224                {
225                    IUserProfileInfo profile =
226                        Framework.Utilities.DataManager.RequestPlugin<IProfileConnector>().GetUserProfile(im.toAgentID);
227                    if (profile != null && profile.IMViaEmail)
228                    {
229                        UserAccount account = m_Scene.UserAccountService.GetUserAccount(null, im.toAgentID.ToString());
230                        if (account != null && !string.IsNullOrEmpty(account.Email))
231                        {
232                            emailModule.SendEmail(UUID.Zero, account.Email,
233                                                  string.Format("Offline Message from {0}", im.fromAgentName),
234                                                  string.Format("Time: {0}\n",
235                                                                Util.ToDateTime(im.timestamp).ToShortDateString()) +
236                                                  string.Format("From: {0}\n", im.fromAgentName) +
237                                                  string.Format("Message: {0}\n", im.message), m_Scene);
238                        }
239                    }
240                }
241
242                if (im.dialog == (byte) InstantMessageDialog.MessageFromAgent && !im.fromGroup)
243                {
244                    client.SendInstantMessage(new GridInstantMessage(
245                                                  null, im.toAgentID,
246                                                  "System", im.fromAgentID,
247                                                  (byte) InstantMessageDialog.MessageFromAgent,
248                                                  "Message saved, reason: " + reason,
249                                                  false, new Vector3()));
250                }
251
252                if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
253                    client.SendAlertMessage("User is not online. Inventory has been saved");
254            }
255            else if (im.offline == 0)
256            {
257                if (client == null) return;
258                if (im.dialog == (byte) InstantMessageDialog.MessageFromAgent && !im.fromGroup)
259                {
260                    client.SendInstantMessage(new GridInstantMessage(
261                                                  null, im.toAgentID,
262                                                  "System", im.fromAgentID,
263                                                  (byte) InstantMessageDialog.MessageFromAgent,
264                                                  "Message saved, reason: " + reason,
265                                                  false, new Vector3()));
266                }
267
268                if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
269                    client.SendAlertMessage("User not able to be found. Inventory has been saved");
270            }
271        }
272    }
273}