using Newtonsoft.Json; using OpenMetaverse; using SecondBotEvents.Config; using System; using System.Linq; using System.Collections; using System.Collections.Generic; namespace SecondBotEvents.Services { public class DataStoreService : Services { protected DataStoreConfig myConfig; protected bool botConnected = false; public DataStoreService(EventsSecondBot setMaster) : base(setMaster) { myConfig = new DataStoreConfig(master.fromEnv,master.fromFolder); } public override string Status() { if(myConfig == null) { return "DataStore Service [Config status broken]"; } return "DataStore Service [Waiting for bot]"; } protected Dictionary avatarsName2Key = new Dictionary(); protected Dictionary avatarsKey2Name = new Dictionary(); protected Dictionary groupsKey2Name = new Dictionary(); protected Dictionary groupsName2Key = new Dictionary(); protected List localChatHistory = new List(); protected Dictionary> chatWindows = new Dictionary>(); // sess, list chat protected Dictionary chatWindowsUnread = new Dictionary(); // sess, bool protected Dictionary chatWindowsIsGroup = new Dictionary(); // sess, bool protected Dictionary chatWindowsOwner = new Dictionary(); // sess, owner id protected void recordChat(UUID sessionID, string fromname, string message) { if(chatWindows.ContainsKey(sessionID) == false) { return; // chat window not open unable to record message } chatWindows[sessionID].Add(fromname + ": " + message); chatWindowsUnread[sessionID] = true; int purgeLen = myConfig.GetImChatHistoryLimit(); if(chatWindowsIsGroup[sessionID] == true) { purgeLen = myConfig.GetGroupChatHistoryLimitPerGroup(); } int counter = chatWindows[sessionID].Count(); while (counter > purgeLen) { chatWindows[sessionID].RemoveAt(0); counter--; } } protected void openChatWindow(bool group, UUID sessionID, UUID ownerID) { if (chatWindows.ContainsKey(sessionID) == true) { return; // window already open } if (chatWindowsOwner.ContainsValue(ownerID) == true) { // new session find the old one and update to this session Dictionary oldOwners = chatWindowsOwner; foreach (KeyValuePair kvp in oldOwners) { if(kvp.Value == ownerID) { chatWindows.Add(sessionID, chatWindows[kvp.Key]); chatWindowsUnread.Add(sessionID, chatWindowsUnread[kvp.Key]); chatWindowsIsGroup.Add(sessionID, chatWindowsIsGroup[kvp.Key]); chatWindowsOwner.Add(sessionID, ownerID); chatWindows.Remove(kvp.Key); chatWindowsUnread.Remove(kvp.Key); chatWindowsIsGroup.Remove(kvp.Key); chatWindowsOwner.Remove(kvp.Key); break; } } return; // chat recovered } chatWindows.Add(sessionID, new List()); chatWindowsUnread.Add(sessionID, false); chatWindowsIsGroup.Add(sessionID, group); chatWindowsOwner.Add(sessionID, ownerID); // new window now open } protected Dictionary> notecardDataStore = new Dictionary>(); public List getLocalChat() { return localChatHistory; } public bool knownGroup(UUID groupId, string name) { if(groupId != UUID.Zero) { return groupsKey2Name.ContainsKey(groupId); } return groupsName2Key.ContainsKey(name); } public List getGroupChat(UUID groupId) { if(chatWindows.ContainsKey(groupId) == false) { return new List(); } return chatWindows[groupId]; } /* * checks if the avatar is known to the system * if not the bot will attempt to * lookup the avatar */ public bool knownAvatar(string name) { return knownAvatar(name, UUID.Zero); } protected int ObjectsAvatarsHash = 0; /* * checks if the avatar is known to the system * if not the bot will attempt to * lookup the avatar */ public bool knownAvatar(string name, UUID avatarId) { int currentHash = master.botClient.client.Network.CurrentSim.ObjectsAvatars.GetHashCode(); if (currentHash != ObjectsAvatarsHash) { ObjectsAvatarsHash = currentHash; List avs = master.botClient.client.Network.CurrentSim.ObjectsAvatars.Copy().Values.ToList(); foreach (Avatar A in avs) { addAvatar(A.ID, A.Name); } } if (avatarId != UUID.Zero) { if(avatarsKey2Name.ContainsKey(avatarId) == false) { master.botClient.client.Avatars.RequestAvatarName(avatarId); return false; } return true; } string[] bits = name.Split(' '); if (bits.Length == 1) { name = name + " Resident"; } if (avatarsName2Key.ContainsKey(name) == false) { master.botClient.client.Avatars.RequestAvatarNameSearch(name, UUID.Random()); return false; } return true; } public string getAvatarName(UUID avatarId) { if(knownAvatar(null, avatarId) == false) { return "lookup"; } return avatarsKey2Name[avatarId]; } public string getAvatarUUID(string name) { if (knownAvatar(name) == false) { return "lookup"; } return avatarsName2Key[name].ToString(); } public List getAvatarIms(UUID avatarId) { if(chatWindowsOwner.ContainsValue(avatarId) == false) { return new List(); } UUID sessionID = UUID.Zero; foreach(KeyValuePair links in chatWindowsOwner) { if(links.Value == avatarId) { sessionID = links.Key; break; } } if (sessionID == UUID.Zero) { return new List(); } return chatWindows[sessionID]; } public Dictionary getAvatarImWindows() { Dictionary windows = new Dictionary(); foreach (KeyValuePair links in chatWindowsIsGroup) { if(links.Value == true) { continue; } if (chatWindowsIsGroup[links.Key] == true) { continue; } windows[chatWindowsOwner[links.Key]] = getAvatarName(chatWindowsOwner[links.Key]); } return windows; } public List getAvatarImWindow(UUID avatarId) { if (chatWindowsOwner.ContainsValue(avatarId) == false) { return new List(); } UUID sessionID = UUID.Zero; foreach (KeyValuePair links in chatWindowsOwner) { if (links.Value == avatarId) { sessionID = links.Key; break; } } if(chatWindowsIsGroup[sessionID] == true) { return new List(); } return chatWindows[sessionID]; } public bool getAvatarImWindowsUnreadAny() { bool replyState = false; foreach (KeyValuePair links in chatWindowsIsGroup) { if (links.Value == true) { continue; } if (chatWindowsIsGroup[links.Key] == true) { continue; } if (chatWindowsUnread[links.Key] == false) { continue; } replyState = true; break; } return replyState; } public List getAvatarImWindowsUnread() { List windows = new List(); foreach (KeyValuePair links in chatWindowsIsGroup) { if (links.Value == true) { continue; } if (chatWindowsIsGroup[links.Key] == true) { continue; } if (chatWindowsUnread[links.Key] == false) { continue; } windows.Add(chatWindowsOwner[links.Key]); } return windows; } protected void reset() { avatarsName2Key = new Dictionary(); avatarsKey2Name = new Dictionary(); groupsKey2Name = new Dictionary(); groupsName2Key = new Dictionary(); localChatHistory = new List(); notecardDataStore = new Dictionary>(); } protected void BotClientRestart(object o, BotClientNotice e) { botConnected = false; Console.WriteLine("DataStore Service [Attached to new client]"); master.botClient.client.Network.LoggedOut += BotLoggedOut; master.botClient.client.Network.SimConnected += BotLoggedIn; } protected void BotLoggedOut(object o, LoggedOutEventArgs e) { botConnected = false; master.botClient.client.Network.SimConnected += BotLoggedIn; Console.WriteLine("DataStore Service [Standby]"); } protected void BotLoggedIn(object o, SimConnectedEventArgs e) { master.botClient.client.Network.SimConnected -= BotLoggedIn; master.botClient.client.Groups.CurrentGroups += GroupCurrent; master.botClient.client.Groups.GroupJoinedReply += GroupJoin; master.botClient.client.Groups.GroupLeaveReply += GroupLeave; master.botClient.client.Avatars.UUIDNameReply += AvatarUUIDName; master.botClient.client.Friends.FriendNames += AvatarFriendNames; master.botClient.client.Self.IM += ImEvent; master.botClient.client.Self.ChatFromSimulator += ChatFromSim; master.botClient.client.Groups.RequestCurrentGroups(); botConnected = true; Console.WriteLine("DataStore Service [Active]"); } readonly string[] hard_blocked_agents = new[] { "secondlife", "second life" }; protected void ChatFromSim(object o, ChatEventArgs e) { switch(e.Type) { case ChatType.Whisper: case ChatType.Normal: case ChatType.Shout: { if (e.SourceType != ChatSourceType.Agent) { break; } if (hard_blocked_agents.Contains(e.FromName.ToLowerInvariant()) == true) { break; } localChatHistory.Add(e.FromName + ": " + e.Message); cleanLocalChat(); break; } default: { break; } } } protected void GroupCurrent(object o, CurrentGroupsEventArgs e) { List missingGroups = groupsKey2Name.Keys.ToList(); foreach(Group G in e.Groups.Values) { missingGroups.Remove(G.ID); if (groupsKey2Name.ContainsKey(G.ID) == true) { continue; } groupsKey2Name.Add(G.ID, G.Name); groupsName2Key.Add(G.Name, G.ID); master.botClient.client.Self.RequestJoinGroupChat(G.ID); } foreach(UUID G in missingGroups) { if (groupsKey2Name.ContainsKey(G) == false) { continue; } string name = groupsKey2Name[G]; groupsKey2Name.Remove(G); groupsName2Key.Remove(name); // @todo remove group chat here } } protected void GroupJoin(object o, GroupOperationEventArgs e) { master.botClient.client.Groups.RequestCurrentGroups(); } protected void GroupLeave(object o, GroupOperationEventArgs e) { master.botClient.client.Groups.RequestCurrentGroups(); } protected void addAvatar(UUID id, string name) { if (avatarsKey2Name.ContainsKey(id) == true) { return; } avatarsKey2Name.Add(id, name); avatarsName2Key.Add(name, id); } protected void AvatarUUIDName(object o, UUIDNameReplyEventArgs e) { foreach(KeyValuePair pair in e.Names) { addAvatar(pair.Key, pair.Value); } } protected void AvatarFriendNames(object o, FriendNamesEventArgs e) { foreach (KeyValuePair pair in e.Names) { addAvatar(pair.Key, pair.Value); } } protected void cleanGroupChat(UUID groupID) { if(groupsKey2Name.ContainsKey(groupID) == false) { return; } // @todo clean group chat here } protected void cleanAvatarChat(UUID avatarID) { if (avatarsKey2Name.ContainsKey(avatarID) == false) { return; } // @todo clean avatar chat here } protected void cleanLocalChat() { if (localChatHistory.Count <= myConfig.GetLocalChatHistoryLimit()) { return; } localChatHistory.RemoveAt(0); } protected void ImEvent(object o, InstantMessageEventArgs e) { switch(e.IM.Dialog) { case InstantMessageDialog.GroupNotice: { if(groupsKey2Name.ContainsKey(e.IM.IMSessionID) == false) { break; } openChatWindow(true, e.IM.IMSessionID, e.IM.IMSessionID); recordChat(e.IM.IMSessionID, "**Notice**", e.IM.Message); break; } case InstantMessageDialog.SessionSend: case InstantMessageDialog.MessageFromAgent: { if (groupsKey2Name.ContainsKey(e.IM.IMSessionID) == true) { // group IM openChatWindow(true, e.IM.IMSessionID, e.IM.IMSessionID); recordChat(e.IM.IMSessionID, e.IM.FromAgentName, e.IM.Message); break; } addAvatar(e.IM.FromAgentID, e.IM.FromAgentName); openChatWindow(false, e.IM.IMSessionID, e.IM.FromAgentID); recordChat(e.IM.IMSessionID, e.IM.FromAgentName, e.IM.Message); break; } default: { break; } } } public override void Start() { Stop(); master.BotClientNoticeEvent += BotClientRestart; Console.WriteLine("DataStore Service [Starting]"); } public override void Stop() { reset(); master.BotClientNoticeEvent -= BotClientRestart; if (master.botClient != null) { if (master.botClient.client != null) { master.botClient.client.Groups.CurrentGroups -= GroupCurrent; master.botClient.client.Groups.GroupJoinedReply -= GroupJoin; master.botClient.client.Groups.GroupLeaveReply -= GroupLeave; master.botClient.client.Avatars.UUIDNameReply -= AvatarUUIDName; master.botClient.client.Friends.FriendNames -= AvatarFriendNames; master.botClient.client.Self.IM -= ImEvent; master.botClient.client.Self.ChatFromSimulator -= ChatFromSim; } } Console.WriteLine("DataStore Service [Stopping]"); } } }