FriendsModule.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.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 OpenSimulator 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. using System;
  28. using System.Collections;
  29. using System.Collections.Generic;
  30. using System.Reflection;
  31. using log4net;
  32. using Nini.Config;
  33. using Nwc.XmlRpc;
  34. using OpenMetaverse;
  35. using OpenSim.Framework;
  36. using OpenSim.Framework.Communications;
  37. using OpenSim.Region.Framework.Interfaces;
  38. using OpenSim.Region.Framework.Scenes;
  39. using OpenSim.Services.Interfaces;
  40. using OpenSim.Services.Connectors.Friends;
  41. using OpenSim.Server.Base;
  42. using OpenSim.Framework.Servers.HttpServer;
  43. using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
  44. using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
  45. using GridRegion = OpenSim.Services.Interfaces.GridRegion;
  46. namespace OpenSim.Region.CoreModules.Avatar.Friends
  47. {
  48. public class FriendsModule : ISharedRegionModule, IFriendsModule
  49. {
  50. protected class UserFriendData
  51. {
  52. public UUID PrincipalID;
  53. public FriendInfo[] Friends;
  54. public int Refcount;
  55. public UUID RegionID;
  56. public bool IsFriend(string friend)
  57. {
  58. foreach (FriendInfo fi in Friends)
  59. {
  60. if (fi.Friend == friend)
  61. return true;
  62. }
  63. return false;
  64. }
  65. }
  66. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  67. protected List<Scene> m_Scenes = new List<Scene>();
  68. protected IPresenceService m_PresenceService = null;
  69. protected IFriendsService m_FriendsService = null;
  70. protected FriendsSimConnector m_FriendsSimConnector;
  71. protected Dictionary<UUID, UserFriendData> m_Friends =
  72. new Dictionary<UUID, UserFriendData>();
  73. protected List<UUID> m_NeedsListOfFriends = new List<UUID>();
  74. protected IPresenceService PresenceService
  75. {
  76. get
  77. {
  78. if (m_PresenceService == null)
  79. {
  80. if (m_Scenes.Count > 0)
  81. m_PresenceService = m_Scenes[0].RequestModuleInterface<IPresenceService>();
  82. }
  83. return m_PresenceService;
  84. }
  85. }
  86. protected IFriendsService FriendsService
  87. {
  88. get
  89. {
  90. if (m_FriendsService == null)
  91. {
  92. if (m_Scenes.Count > 0)
  93. m_FriendsService = m_Scenes[0].RequestModuleInterface<IFriendsService>();
  94. }
  95. return m_FriendsService;
  96. }
  97. }
  98. protected IGridService GridService
  99. {
  100. get { return m_Scenes[0].GridService; }
  101. }
  102. public IUserAccountService UserAccountService
  103. {
  104. get { return m_Scenes[0].UserAccountService; }
  105. }
  106. public IScene Scene
  107. {
  108. get
  109. {
  110. if (m_Scenes.Count > 0)
  111. return m_Scenes[0];
  112. else
  113. return null;
  114. }
  115. }
  116. public void Initialise(IConfigSource config)
  117. {
  118. IConfig friendsConfig = config.Configs["Friends"];
  119. if (friendsConfig != null)
  120. {
  121. int mPort = friendsConfig.GetInt("Port", 0);
  122. string connector = friendsConfig.GetString("Connector", String.Empty);
  123. Object[] args = new Object[] { config };
  124. m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(connector, args);
  125. m_FriendsSimConnector = new FriendsSimConnector();
  126. // Instantiate the request handler
  127. IHttpServer server = MainServer.GetHttpServer((uint)mPort);
  128. server.AddStreamHandler(new FriendsRequestHandler(this));
  129. }
  130. if (m_FriendsService == null)
  131. {
  132. m_log.Error("[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue");
  133. throw new Exception("Connector load error");
  134. }
  135. }
  136. public void PostInitialise()
  137. {
  138. }
  139. public void Close()
  140. {
  141. }
  142. public void AddRegion(Scene scene)
  143. {
  144. m_Scenes.Add(scene);
  145. scene.RegisterModuleInterface<IFriendsModule>(this);
  146. scene.EventManager.OnNewClient += OnNewClient;
  147. scene.EventManager.OnClientClosed += OnClientClosed;
  148. scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
  149. scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
  150. scene.EventManager.OnClientLogin += OnClientLogin;
  151. }
  152. public void RegionLoaded(Scene scene)
  153. {
  154. }
  155. public void RemoveRegion(Scene scene)
  156. {
  157. m_Scenes.Remove(scene);
  158. }
  159. public string Name
  160. {
  161. get { return "FriendsModule"; }
  162. }
  163. public Type ReplaceableInterface
  164. {
  165. get { return null; }
  166. }
  167. public uint GetFriendPerms(UUID principalID, UUID friendID)
  168. {
  169. if (!m_Friends.ContainsKey(principalID))
  170. return 0;
  171. UserFriendData data = m_Friends[principalID];
  172. foreach (FriendInfo fi in data.Friends)
  173. {
  174. if (fi.Friend == friendID.ToString())
  175. return (uint)fi.TheirFlags;
  176. }
  177. return 0;
  178. }
  179. private void OnNewClient(IClientAPI client)
  180. {
  181. client.OnInstantMessage += OnInstantMessage;
  182. client.OnApproveFriendRequest += OnApproveFriendRequest;
  183. client.OnDenyFriendRequest += OnDenyFriendRequest;
  184. client.OnTerminateFriendship += OnTerminateFriendship;
  185. client.OnGrantUserRights += OnGrantUserRights;
  186. lock (m_Friends)
  187. {
  188. if (m_Friends.ContainsKey(client.AgentId))
  189. {
  190. m_Friends[client.AgentId].Refcount++;
  191. return;
  192. }
  193. UserFriendData newFriends = new UserFriendData();
  194. newFriends.PrincipalID = client.AgentId;
  195. newFriends.Friends = m_FriendsService.GetFriends(client.AgentId);
  196. newFriends.Refcount = 1;
  197. newFriends.RegionID = UUID.Zero;
  198. m_Friends.Add(client.AgentId, newFriends);
  199. }
  200. }
  201. private void OnClientClosed(UUID agentID, Scene scene)
  202. {
  203. ScenePresence sp = scene.GetScenePresence(agentID);
  204. if (sp != null && !sp.IsChildAgent)
  205. // do this for root agents closing out
  206. StatusChange(agentID, false);
  207. lock (m_Friends)
  208. if (m_Friends.ContainsKey(agentID))
  209. {
  210. if (m_Friends[agentID].Refcount == 1)
  211. m_Friends.Remove(agentID);
  212. else
  213. m_Friends[agentID].Refcount--;
  214. }
  215. }
  216. private void OnMakeRootAgent(ScenePresence sp)
  217. {
  218. UUID agentID = sp.ControllingClient.AgentId;
  219. if (m_Friends.ContainsKey(agentID))
  220. {
  221. // This is probably an overkill, but just
  222. // to make sure we have the latest and greatest
  223. // friends list -- always pull OnMakeRoot
  224. m_Friends[agentID].Friends =
  225. m_FriendsService.GetFriends(agentID);
  226. m_Friends[agentID].RegionID =
  227. sp.ControllingClient.Scene.RegionInfo.RegionID;
  228. }
  229. }
  230. private void OnMakeChildAgent(ScenePresence sp)
  231. {
  232. UUID agentID = sp.ControllingClient.AgentId;
  233. if (m_Friends.ContainsKey(agentID))
  234. {
  235. if (m_Friends[agentID].RegionID == sp.ControllingClient.Scene.RegionInfo.RegionID)
  236. m_Friends[agentID].RegionID = UUID.Zero;
  237. }
  238. }
  239. private void OnClientLogin(IClientAPI client)
  240. {
  241. UUID agentID = client.AgentId;
  242. // Inform the friends that this user is online
  243. StatusChange(agentID, true);
  244. // Register that we need to send the list of online friends to this user
  245. lock (m_NeedsListOfFriends)
  246. if (!m_NeedsListOfFriends.Contains(agentID))
  247. {
  248. m_NeedsListOfFriends.Add(agentID);
  249. }
  250. }
  251. public void SendFriendsOnlineIfNeeded(IClientAPI client)
  252. {
  253. UUID agentID = client.AgentId;
  254. if (m_NeedsListOfFriends.Contains(agentID))
  255. {
  256. if (!m_Friends.ContainsKey(agentID))
  257. {
  258. m_log.DebugFormat("[FRIENDS MODULE]: agent {0} not found in local cache", agentID);
  259. return;
  260. }
  261. //
  262. // Send the friends online
  263. //
  264. List<UUID> online = GetOnlineFriends(agentID);
  265. if (online.Count > 0)
  266. {
  267. m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count);
  268. client.SendAgentOnline(online.ToArray());
  269. }
  270. //
  271. // Send outstanding friendship offers
  272. //
  273. if (m_Friends.ContainsKey(agentID))
  274. {
  275. List<string> outstanding = new List<string>();
  276. foreach (FriendInfo fi in m_Friends[agentID].Friends)
  277. if (fi.TheirFlags == -1)
  278. outstanding.Add(fi.Friend);
  279. GridInstantMessage im = new GridInstantMessage(client.Scene, UUID.Zero, "", agentID, (byte)InstantMessageDialog.FriendshipOffered, "Will you be my friend?", true, Vector3.Zero);
  280. foreach (string fid in outstanding)
  281. {
  282. try
  283. {
  284. im.fromAgentID = new Guid(fid);
  285. }
  286. catch
  287. {
  288. continue;
  289. }
  290. UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, new UUID(im.fromAgentID));
  291. im.fromAgentName = account.FirstName + " " + account.LastName;
  292. PresenceInfo presence = null;
  293. PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid });
  294. if (presences != null && presences.Length > 0)
  295. presence = presences[0];
  296. if (presence != null)
  297. im.offline = 0;
  298. im.imSessionID = im.fromAgentID;
  299. // Finally
  300. LocalFriendshipOffered(agentID, im);
  301. }
  302. }
  303. lock (m_NeedsListOfFriends)
  304. m_NeedsListOfFriends.Remove(agentID);
  305. }
  306. }
  307. List<UUID> GetOnlineFriends(UUID userID)
  308. {
  309. List<string> friendList = new List<string>();
  310. List<UUID> online = new List<UUID>();
  311. foreach (FriendInfo fi in m_Friends[userID].Friends)
  312. {
  313. if (((fi.TheirFlags & 1) != 0) && (fi.TheirFlags != -1))
  314. friendList.Add(fi.Friend);
  315. }
  316. if (friendList.Count == 0)
  317. // no friends whatsoever
  318. return online;
  319. PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
  320. foreach (PresenceInfo pi in presence)
  321. online.Add(new UUID(pi.UserID));
  322. //m_log.DebugFormat("[XXX] {0} friend online {1}", userID, pi.UserID);
  323. return online;
  324. }
  325. //
  326. // Find the client for a ID
  327. //
  328. public IClientAPI LocateClientObject(UUID agentID)
  329. {
  330. Scene scene = GetClientScene(agentID);
  331. if (scene == null)
  332. return null;
  333. ScenePresence presence = scene.GetScenePresence(agentID);
  334. if (presence == null)
  335. return null;
  336. return presence.ControllingClient;
  337. }
  338. //
  339. // Find the scene for an agent
  340. //
  341. private Scene GetClientScene(UUID agentId)
  342. {
  343. lock (m_Scenes)
  344. {
  345. foreach (Scene scene in m_Scenes)
  346. {
  347. ScenePresence presence = scene.GetScenePresence(agentId);
  348. if (presence != null)
  349. {
  350. if (!presence.IsChildAgent)
  351. return scene;
  352. }
  353. }
  354. }
  355. return null;
  356. }
  357. /// <summary>
  358. /// Caller beware! Call this only for root agents.
  359. /// </summary>
  360. /// <param name="agentID"></param>
  361. /// <param name="online"></param>
  362. private void StatusChange(UUID agentID, bool online)
  363. {
  364. //m_log.DebugFormat("[FRIENDS]: StatusChange {0}", online);
  365. if (m_Friends.ContainsKey(agentID))
  366. {
  367. //m_log.DebugFormat("[FRIENDS]: # of friends: {0}", m_Friends[agentID].Friends.Length);
  368. List<FriendInfo> friendList = new List<FriendInfo>();
  369. foreach (FriendInfo fi in m_Friends[agentID].Friends)
  370. {
  371. if (((fi.MyFlags & 1) != 0) && (fi.TheirFlags != -1))
  372. friendList.Add(fi);
  373. }
  374. Util.FireAndForget(delegate
  375. {
  376. foreach (FriendInfo fi in friendList)
  377. {
  378. //m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID);
  379. // Notify about this user status
  380. StatusNotify(fi, agentID, online);
  381. }
  382. });
  383. }
  384. else
  385. m_log.WarnFormat("[FRIENDS]: {0} not found in cache", agentID);
  386. }
  387. private void StatusNotify(FriendInfo friend, UUID userID, bool online)
  388. {
  389. UUID friendID = UUID.Zero;
  390. if (UUID.TryParse(friend.Friend, out friendID))
  391. {
  392. // Try local
  393. if (LocalStatusNotification(userID, friendID, online))
  394. return;
  395. // The friend is not here [as root]. Let's forward.
  396. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
  397. if (friendSessions != null && friendSessions.Length > 0)
  398. {
  399. PresenceInfo friendSession = null;
  400. foreach (PresenceInfo pinfo in friendSessions)
  401. if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
  402. {
  403. friendSession = pinfo;
  404. break;
  405. }
  406. if (friendSession != null)
  407. {
  408. GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
  409. //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
  410. m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
  411. }
  412. }
  413. // Friend is not online. Ignore.
  414. }
  415. else
  416. m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
  417. }
  418. private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
  419. {
  420. if (im.dialog == (byte)OpenMetaverse.InstantMessageDialog.FriendshipOffered)
  421. {
  422. // we got a friendship offer
  423. UUID principalID = new UUID(im.fromAgentID);
  424. UUID friendID = new UUID(im.toAgentID);
  425. m_log.DebugFormat("[FRIENDS]: {0} ({1}) offered friendship to {2}", principalID, im.fromAgentName, friendID);
  426. // This user wants to be friends with the other user.
  427. // Let's add the relation backwards, in case the other is not online
  428. FriendsService.StoreFriend(friendID, principalID.ToString(), 0);
  429. // Now let's ask the other user to be friends with this user
  430. ForwardFriendshipOffer(principalID, friendID, im);
  431. }
  432. }
  433. private void ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im)
  434. {
  435. // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID)
  436. // We stick this agent's ID as imSession, so that it's directly available on the receiving end
  437. im.imSessionID = im.fromAgentID;
  438. // Try the local sim
  439. UserAccount account = UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, agentID);
  440. im.fromAgentName = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
  441. if (LocalFriendshipOffered(friendID, im))
  442. return;
  443. // The prospective friend is not here [as root]. Let's forward.
  444. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
  445. if (friendSessions != null && friendSessions.Length > 0)
  446. {
  447. PresenceInfo friendSession = friendSessions[0];
  448. if (friendSession != null)
  449. {
  450. GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
  451. m_FriendsSimConnector.FriendshipOffered(region, agentID, friendID, im.message);
  452. }
  453. }
  454. // If the prospective friend is not online, he'll get the message upon login.
  455. }
  456. private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
  457. {
  458. m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID);
  459. FriendsService.StoreFriend(agentID, friendID.ToString(), 1);
  460. FriendsService.StoreFriend(friendID, agentID.ToString(), 1);
  461. // update the local cache
  462. m_Friends[agentID].Friends = FriendsService.GetFriends(agentID);
  463. //
  464. // Notify the friend
  465. //
  466. // Try Local
  467. if (LocalFriendshipApproved(agentID, client.Name, friendID))
  468. {
  469. client.SendAgentOnline(new UUID[] { friendID });
  470. return;
  471. }
  472. // The friend is not here
  473. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
  474. if (friendSessions != null && friendSessions.Length > 0)
  475. {
  476. PresenceInfo friendSession = friendSessions[0];
  477. if (friendSession != null)
  478. {
  479. GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
  480. m_FriendsSimConnector.FriendshipApproved(region, agentID, client.Name, friendID);
  481. client.SendAgentOnline(new UUID[] { friendID });
  482. }
  483. }
  484. }
  485. private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
  486. {
  487. m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID);
  488. FriendsService.Delete(agentID, friendID.ToString());
  489. FriendsService.Delete(friendID, agentID.ToString());
  490. //
  491. // Notify the friend
  492. //
  493. // Try local
  494. if (LocalFriendshipDenied(agentID, client.Name, friendID))
  495. return;
  496. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
  497. if (friendSessions != null && friendSessions.Length > 0)
  498. {
  499. PresenceInfo friendSession = friendSessions[0];
  500. if (friendSession != null)
  501. {
  502. GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
  503. if (region != null)
  504. m_FriendsSimConnector.FriendshipDenied(region, agentID, client.Name, friendID);
  505. else
  506. m_log.WarnFormat("[FRIENDS]: Could not find region {0} in locating {1}", friendSession.RegionID, friendID);
  507. }
  508. }
  509. }
  510. private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID)
  511. {
  512. FriendsService.Delete(agentID, exfriendID.ToString());
  513. FriendsService.Delete(exfriendID, agentID.ToString());
  514. // Update local cache
  515. m_Friends[agentID].Friends = FriendsService.GetFriends(agentID);
  516. client.SendTerminateFriend(exfriendID);
  517. //
  518. // Notify the friend
  519. //
  520. // Try local
  521. if (LocalFriendshipTerminated(exfriendID))
  522. return;
  523. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() });
  524. if (friendSessions != null && friendSessions.Length > 0)
  525. {
  526. PresenceInfo friendSession = friendSessions[0];
  527. if (friendSession != null)
  528. {
  529. GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
  530. m_FriendsSimConnector.FriendshipTerminated(region, agentID, exfriendID);
  531. }
  532. }
  533. }
  534. private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
  535. {
  536. if (!m_Friends.ContainsKey(remoteClient.AgentId))
  537. return;
  538. m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
  539. // Let's find the friend in this user's friend list
  540. UserFriendData fd = m_Friends[remoteClient.AgentId];
  541. FriendInfo friend = null;
  542. foreach (FriendInfo fi in fd.Friends)
  543. if (fi.Friend == target.ToString())
  544. friend = fi;
  545. if (friend != null) // Found it
  546. {
  547. // Store it on the DB
  548. FriendsService.StoreFriend(requester, target.ToString(), rights);
  549. // Store it in the local cache
  550. int myFlags = friend.MyFlags;
  551. friend.MyFlags = rights;
  552. // Always send this back to the original client
  553. remoteClient.SendChangeUserRights(requester, target, rights);
  554. //
  555. // Notify the friend
  556. //
  557. // Try local
  558. if (LocalGrantRights(requester, target, myFlags, rights))
  559. return;
  560. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { target.ToString() });
  561. if (friendSessions != null && friendSessions.Length > 0)
  562. {
  563. PresenceInfo friendSession = friendSessions[0];
  564. if (friendSession != null)
  565. {
  566. GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
  567. // TODO: You might want to send the delta to save the lookup
  568. // on the other end!!
  569. m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights);
  570. }
  571. }
  572. }
  573. }
  574. #region Local
  575. public bool LocalFriendshipOffered(UUID toID, GridInstantMessage im)
  576. {
  577. IClientAPI friendClient = LocateClientObject(toID);
  578. if (friendClient != null)
  579. {
  580. // the prospective friend in this sim as root agent
  581. friendClient.SendInstantMessage(im);
  582. // we're done
  583. return true;
  584. }
  585. return false;
  586. }
  587. public bool LocalFriendshipApproved(UUID userID, string userName, UUID friendID)
  588. {
  589. IClientAPI friendClient = LocateClientObject(friendID);
  590. if (friendClient != null)
  591. {
  592. // the prospective friend in this sim as root agent
  593. GridInstantMessage im = new GridInstantMessage(Scene, userID, userName, friendID,
  594. (byte)OpenMetaverse.InstantMessageDialog.FriendshipAccepted, userID.ToString(), false, Vector3.Zero);
  595. friendClient.SendInstantMessage(im);
  596. // update the local cache
  597. m_Friends[friendID].Friends = FriendsService.GetFriends(friendID);
  598. // we're done
  599. return true;
  600. }
  601. return false;
  602. }
  603. public bool LocalFriendshipDenied(UUID userID, string userName, UUID friendID)
  604. {
  605. IClientAPI friendClient = LocateClientObject(friendID);
  606. if (friendClient != null)
  607. {
  608. // the prospective friend in this sim as root agent
  609. GridInstantMessage im = new GridInstantMessage(Scene, userID, userName, friendID,
  610. (byte)OpenMetaverse.InstantMessageDialog.FriendshipDeclined, userID.ToString(), false, Vector3.Zero);
  611. friendClient.SendInstantMessage(im);
  612. // we're done
  613. return true;
  614. }
  615. return false;
  616. }
  617. public bool LocalFriendshipTerminated(UUID exfriendID)
  618. {
  619. IClientAPI friendClient = LocateClientObject(exfriendID);
  620. if (friendClient != null)
  621. {
  622. // the friend in this sim as root agent
  623. friendClient.SendTerminateFriend(exfriendID);
  624. // update local cache
  625. m_Friends[exfriendID].Friends = FriendsService.GetFriends(exfriendID);
  626. // we're done
  627. return true;
  628. }
  629. return false;
  630. }
  631. public bool LocalGrantRights(UUID userID, UUID friendID, int userFlags, int rights)
  632. {
  633. IClientAPI friendClient = LocateClientObject(friendID);
  634. if (friendClient != null)
  635. {
  636. bool onlineBitChanged = ((rights ^ userFlags) & (int)FriendRights.CanSeeOnline) != 0;
  637. if (onlineBitChanged)
  638. {
  639. if ((rights & (int)FriendRights.CanSeeOnline) == 1)
  640. friendClient.SendAgentOnline(new UUID[] { new UUID(userID) });
  641. else
  642. friendClient.SendAgentOffline(new UUID[] { new UUID(userID) });
  643. }
  644. else
  645. {
  646. bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0;
  647. if (canEditObjectsChanged)
  648. friendClient.SendChangeUserRights(userID, friendID, rights);
  649. }
  650. // update local cache
  651. //m_Friends[friendID].Friends = m_FriendsService.GetFriends(friendID);
  652. foreach (FriendInfo finfo in m_Friends[friendID].Friends)
  653. if (finfo.Friend == userID.ToString())
  654. finfo.TheirFlags = rights;
  655. return true;
  656. }
  657. return false;
  658. }
  659. public bool LocalStatusNotification(UUID userID, UUID friendID, bool online)
  660. {
  661. IClientAPI friendClient = LocateClientObject(friendID);
  662. if (friendClient != null)
  663. {
  664. //m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online);
  665. // the friend in this sim as root agent
  666. if (online)
  667. friendClient.SendAgentOnline(new UUID[] { userID });
  668. else
  669. friendClient.SendAgentOffline(new UUID[] { userID });
  670. // we're done
  671. return true;
  672. }
  673. return false;
  674. }
  675. #endregion
  676. }
  677. }