From 24f28d353427d1905ae1a46408841265379e29c3 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 23 May 2011 19:45:39 -0700 Subject: HG friends: Status notifications working. Also initial logins get the online friends in other grids. --- .../CoreModules/Avatar/Friends/HGFriendsModule.cs | 162 ++++++++++++++++++++- 1 file changed, 160 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs') diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index c55839f..b0a7567 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -46,7 +46,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Region.CoreModules.Avatar.Friends { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule + public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -56,6 +56,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends get { return "HGFriendsModule"; } } + public override void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + base.AddRegion(scene); + scene.RegisterModuleInterface(this); + } + + #endregion + + #region IFriendsSimConnector + + /// + /// Notify the user that the friend's status changed + /// + /// user to be notified + /// friend whose status changed + /// status + /// + public bool StatusNotify(UUID userID, UUID friendID, bool online) + { + return LocalStatusNotification(friendID, userID, online); + } + #endregion protected override bool FetchFriendslist(IClientAPI client) @@ -103,6 +128,140 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return false; } + protected override void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) + { + // Let's single out the UUIs + List localFriends = new List(); + List foreignFriends = new List(); + string tmp = string.Empty; + + foreach (string s in friendList) + { + UUID id; + if (UUID.TryParse(s, out id)) + localFriends.Add(s); + else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp)) + { + foreignFriends.Add(s); + // add it here too, who knows maybe the foreign friends happens to be on this grid + localFriends.Add(id.ToString()); + } + } + + // OK, see who's present on this grid + List toBeRemoved = new List(); + PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray()); + foreach (PresenceInfo pi in presence) + { + UUID presenceID; + if (UUID.TryParse(pi.UserID, out presenceID)) + { + online.Add(presenceID); + foreach (string s in foreignFriends) + if (s.StartsWith(pi.UserID)) + toBeRemoved.Add(s); + } + } + + foreach (string s in toBeRemoved) + foreignFriends.Remove(s); + + // OK, let's send this up the stack, and leave a closure here + // collecting online friends in other grids + Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); }); + + } + + private void CollectOnlineFriendsElsewhere(UUID userID, List foreignFriends) + { + // let's divide the friends on a per-domain basis + Dictionary> friendsPerDomain = new Dictionary>(); + foreach (string friend in foreignFriends) + { + UUID friendID; + if (!UUID.TryParse(friend, out friendID)) + { + // it's a foreign friend + string url = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp)) + { + if (!friendsPerDomain.ContainsKey(url)) + friendsPerDomain[url] = new List(); + friendsPerDomain[url].Add(friend); + } + } + } + + // Now, call those worlds + + foreach (KeyValuePair> kvp in friendsPerDomain) + { + List ids = new List(); + foreach (string f in kvp.Value) + ids.Add(f); + UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + List online = uConn.GetOnlineFriends(userID, ids); + // Finally send the notifications to the user + // this whole process may take a while, so let's check at every + // iteration that the user is still here + IClientAPI client = LocateClientObject(userID); + if (client != null) + client.SendAgentOnline(online.ToArray()); + else + break; + } + + } + + protected override void StatusNotify(List friendList, UUID userID, bool online) + { + // First, let's divide the friends on a per-domain basis + Dictionary> friendsPerDomain = new Dictionary>(); + foreach (FriendInfo friend in friendList) + { + UUID friendID; + if (UUID.TryParse(friend.Friend, out friendID)) + { + if (!friendsPerDomain.ContainsKey("local")) + friendsPerDomain["local"] = new List(); + friendsPerDomain["local"].Add(friend); + } + else + { + // it's a foreign friend + string url = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out tmp, out tmp, out tmp)) + { + // Let's try our luck in the local sim. Who knows, maybe it's here + if (LocalStatusNotification(userID, friendID, online)) + continue; + + if (!friendsPerDomain.ContainsKey(url)) + friendsPerDomain[url] = new List(); + friendsPerDomain[url].Add(friend); + } + } + } + + // For the local friends, just call the base method + // Let's do this first of all + if (friendsPerDomain.ContainsKey("local")) + base.StatusNotify(friendsPerDomain["local"], userID, online); + + foreach (KeyValuePair> kvp in friendsPerDomain) + { + if (kvp.Key != "local") + { + // For the others, call the user agent service + List ids = new List(); + foreach (FriendInfo f in kvp.Value) + ids.Add(f.Friend); + UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + uConn.StatusNotification(ids, userID, online); + } + } + } + protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) { first = "Unknown"; last = "User"; @@ -172,7 +331,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); - m_log.DebugFormat("[XXX] GetFriendsFromService to {0}", agentUUI); finfos = FriendsService.GetFriends(agentUUI); m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI); } -- cgit v1.1