using Bot.CommandSystem; using Newtonsoft.Json; using OpenMetaverse; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Net; using System.Text; using System.Threading; using OpenMetaverse.Packets; using Bot.Assemble; using OpenMetaverse.Interfaces; using LibZNI; using System.Security.Cryptography; using System.Reflection; namespace Bot { public class Program : BaseCommands { public static Logger Log; public static string BotVer = ASMInfo.BotVer; public static string BotStr = ASMInfo.BotName; // internal identifier for linden public static string Flavor = "Bot"; // inworld identification - must be customized public static SerialManager SM = new SerialManager(); public static GridClient client = new GridClient(); public static bool g_iIsRunning = true; public static CommandRegistry registry; public static List g_ZPrograms = new List(); public static CommandManager CM = null; static readonly object _CacheLock = new object(); //public static License LicenseKey; // Not to be used yet public static void msg(Destinations D, UUID x, string m) { MessageFactory.Post(D, m, x); } public static void passArguments(string data) { CM.RunChatCommand(data); } public static unsafe void Main(string[] args) { File.WriteAllText("PID.lock", Process.GetCurrentProcess().Id.ToString()); if (!Directory.Exists("BotData")) Directory.CreateDirectory("BotData"); Directory.SetCurrentDirectory("BotData"); Console.WriteLine("Setting up Main Configuration"); Log = new Logger("BotCore5"); BotSession.Instance.Logger = Log; BotSession.Instance.LaunchTime = DateTime.Now; ZHash.Instance.NewKey(); ZHash.Instance.Key = "Test"; Console.WriteLine("ZHash (Test): " + ZHash.Instance.Key); MainConfiguration.Instance.Load(); MainConfiguration conf = MainConfiguration.Instance; //MasterObjectCaches = ObjectCaches.Instance; if (args.Length == 2) { // Check if this is activation command if (args[0] == "-a") { MainConfiguration.Instance.ActivationCode = args[1]; MainConfiguration.Instance.Save(); return; } } else if (args.Length == 4) { if (args[0] == "-l") { MainConfiguration.Instance.first = args[1]; MainConfiguration.Instance.last = args[2]; MainConfiguration.Instance.password = args[3]; MainConfiguration.Instance.Save(); return; } } // Initiate bot login // Main thread must be caught in the bot loop so it does not terminate early. // Other programs may hook into the bot to control it /* if (conf.ActivationCode != "") { License L = new License(); L.NewKey(); L.InitUniqueMachine(); L.Key = conf.ActivationCode; License def = new License(); def.NewKey(); def.InitUniqueMachine(); string Reply; HttpWebRequest _request = (HttpWebRequest)WebRequest.Create("http://bak.cloud.xsinode.net/act_handle.php?r=verify&act=" + conf.ActivationCode + "&LIC=" + L.Key + "&mac="+def.Key); using (HttpWebResponse response = (HttpWebResponse)_request.GetResponse()) using (Stream str = response.GetResponseStream()) using (StreamReader sr = new StreamReader(str)) { Reply = sr.ReadToEnd(); } string[] ReplyData = Reply.Split('|'); if(ReplyData[0] == "deny") { WebClient wc = new WebClient(); if (File.Exists("Activator.exe")) File.Delete("Activator.exe"); wc.DownloadFile("http://bak.cloud.xsinode.net/znibot/Activator.exe", "Activator.exe"); int E_CODE = -1; if (ReplyData[1] == "TOO_MANY") E_CODE = 90; else if (ReplyData[1] == "EXPIRED") E_CODE = 32; else if (ReplyData[1] == "INVALID") E_CODE = 100; else E_CODE = 55; string batchContents = "@echo off" + "\ntimeout 5\n" + "cd " + Directory.GetCurrentDirectory()+"\n" + "Activator.exe -d -m " + E_CODE.ToString(); File.WriteAllText("denyAct.bat", batchContents); Process p = Process.Start("denyAct.bat"); return; } else if(ReplyData[0] == "allow") { // Handle expiry on server! // Activate now } else { WebClient wc = new WebClient(); if (File.Exists("Activator.exe")) File.Delete("Activator.exe"); wc.DownloadFile("http://bak.cloud.xsinode.net/znibot/Activator.exe", "Activator.exe"); int E_CODE = 55; // Unknown reply. Activator will not permit logging in until the server can be reached safely. string batchContents = "@echo off" + "\ntimeout 5\n" + "cd " + Directory.GetCurrentDirectory() + "\n" + "Activator.exe -d -m " + E_CODE.ToString(); File.WriteAllText("denyAct.bat", batchContents); Process p = Process.Start("denyAct.bat"); return; } } else { Console.WriteLine("ERROR: You must have an activation code set prior to running Bot.exe!!\n \n[Please run Activator with the Confirmation Number]"); Console.ReadKey(); return; } */ BotSession.Instance.MSGSVC.MessageEvent += MSGSVC_onChat; BotSession.Instance.MSGSVC.MessageEvent += MSGSVC_onIM; BotSession.Instance.MSGSVC.MessageEvent += MSGSVC_onGroupMessage; string fna = null; string lna = null; string pwd = null; if (conf.first == null || conf.first == "") { if (args.Length == 0) { Log.info(false, "Please enter your avatar's first name: "); fna = Console.ReadLine(); Log.info(false, "Please enter the last name: "); lna = Console.ReadLine(); Log.info(false, "Now enter your password: "); pwd = Console.ReadLine(); conf.ConfigFor = "ZBotCore"; conf.ConfigVersion = 1.0f; } else { Log.info(false, "Loading..."); Log.info(false, "FirstName: " + args[0]); fna = args[0]; lna = args[1]; pwd = args[2]; // Continue boot } conf.first = fna; conf.last = lna; conf.password = pwd; conf.Save(); } else { fna = conf.first; lna = conf.last; pwd = conf.password; } bool startupSeq = true; if (File.Exists("ObjectCache.bdf")) File.Delete("ObjectCache.bdf"); client.Self.ChatFromSimulator += onChatRecv; client.Self.GroupChatJoined += onJoinGroupChat; client.Self.IM += onIMEvent; client.Groups.GroupRoleDataReply += CacheGroupRoles; //client.Objects.ObjectUpdate += onObjectUpdate; //client.Objects.ObjectProperties += onObjectProperties; //client.Network.SimChanged += onSimChange; // Recache prims for this sim //client.Objects.TerseObjectUpdate += onObjectTerseUpdate; client.Settings.OBJECT_TRACKING = true; client.Settings.ALWAYS_DECODE_OBJECTS = true; client.Settings.USE_ASSET_CACHE = true; client.Throttle.Asset = 100000; client.Throttle.Land = 100000; client.Throttle.Task = 100000; client.Throttle.Total = 100000; client.Settings.LOG_RESENDS = false; client.Settings.LOG_ALL_CAPS_ERRORS = false; client.Settings.LOG_DISKCACHE = false; client.Settings.ALWAYS_REQUEST_OBJECTS = true; Console.WriteLine("Logging in..."); bool LoggedIn = client.Network.Login(fna, lna, pwd, BotStr, BotVer.ToString()); Console.WriteLine("Logged In: " + LoggedIn.ToString()); if (!LoggedIn) { Console.WriteLine("Check Creds:\n \nFirst Name: '" + fna + "'\nLast Name: '" + lna + "'\nPWD: '" + pwd + "'\nBotStr: '" + BotStr + "'\nBotVer: " + BotVer.ToString()+"\n \nLogin Message: "+client.Network.LoginMessage); } if (LoggedIn) { // Setup BotSession Singleton! BotSession.Instance.grid = client; BotSession.Instance.Logger = Log; Thread prompter = new Thread(() => { BotSession.Instance.Logger.DoPrompt(); }); prompter.Start(); CM = new CommandManager(); MainConfiguration.Instance.Save(); // Flush the config, to update the file format g_ZPrograms = new List(); // Scan folder for plugins, then load FileInfo[] files = new DirectoryInfo(Directory.GetCurrentDirectory()).GetFiles(); foreach(FileInfo fi in files) { try { if (fi.Extension.ToLower() == ".dll") { PluginActivator PA = new PluginActivator(); Assembly asm = PA.LoadLibrary(fi.FullName); List plugins = PA.Activate(asm); foreach (IProgram prog in plugins) { try { if (!g_ZPrograms.Contains(prog)) { Console.WriteLine("Plugin [" + prog.ProgramName + "] found (" + fi.FullName + ") loaded and activated"); prog.run(); g_ZPrograms.Add(prog); } } catch (Exception e) { } } } }catch(Exception e) { Console.WriteLine("Could not load file: " + fi.FullName+" as a Bot Plugin"); } } CommandRegistry.Instance.LocateCommands(); if (!File.Exists("Inventory.blob")) { BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.Store.RootFolder.OwnerID, BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Animation), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Bodypart), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.CallingCard), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Clothing), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Folder), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Gesture), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.ImageJPEG), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.ImageTGA), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Landmark), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Link), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.LinkFolder), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.LSLBytecode), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.LSLText), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Mesh), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Notecard), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Object), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Person), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Simstate), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Sound), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.SoundWAV), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Texture), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.TextureTGA), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Unknown), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); BotSession.Instance.grid.Inventory.RequestFolderContents(BotSession.Instance.grid.Inventory.FindFolderForType(AssetType.Widget), BotSession.Instance.grid.Inventory.Store.Owner, true, true, InventorySortOrder.SystemFoldersToTop); } else BotSession.Instance.grid.Inventory.Store.RestoreFromDisk("Inventory.blob"); int iLastInvLength = 0; while (g_iIsRunning) { if(iLastInvLength != BotSession.Instance.grid.Inventory.Store.Items.Count) { BotSession.Instance.grid.Inventory.Store.SaveToDisk("Inventory.blob"); iLastInvLength = BotSession.Instance.grid.Inventory.Store.Items.Count; } string consoleCmd = "N/A"; try { consoleCmd = BotSession.Instance.Logger.CheckForNewCmd(); }catch(Exception e) { // no command is set yet! } switch (consoleCmd) { case "N/A": { break; } default: { // Run command! Dictionary argsx = new Dictionary(); argsx.Add("type", "console"); argsx.Add("source", "null"); argsx.Add("request", consoleCmd); argsx.Add("from", ""); argsx.Add("from_sess", ""); argsx.Add("fromName", "CONSOLE"); passArguments(JsonConvert.SerializeObject(argsx)); break; } } // Pass to the command handlers client.Self.RetrieveInstantMessages(); if (client.Network.Connected == false) g_iIsRunning = false; // Quit the program and restart immediately! Thread.Sleep(1000); if (conf.ConfigFor == "Main") { MessageFactory.Post(Destinations.DEST_LOCAL, "Alert: Main.json is not fully initialized. Setting default values", UUID.Zero); conf.ConfigFor = "BOT"; conf.ConfigVersion = 1.0f; // data contains nothing at the moment. SM.Write("Main", conf); conf = null; conf = SM.Read("Main"); if (conf.ConfigFor == "BOT") { MessageFactory.Post(Destinations.DEST_LOCAL, "Main.json has been created", UUID.Zero); } else { MessageFactory.Post(Destinations.DEST_LOCAL, "Main.json is invalid. Cannot continue", UUID.Zero); g_iIsRunning = false; } } else { Flavor = conf.ConfigFor; } //msg(MessageHandler.Destinations.DEST_LOCAL, UUID.Zero, "Commands found: " + registry.Cmds.Count.ToString()); if (startupSeq) { registry = CommandRegistry.Instance; registry.LocateCommands(); GroupsCache = new Dictionary(); ReloadGroupsCache(); //ReloadGroupsCache(); try { Log.info(true, g_ZPrograms.Count.ToString() + " programs linked"); //if (g_ZPrograms.Count > 0) msg(MessageHandler.Destinations.DEST_LOCAL, UUID.Zero, "Default Program [" + conf.MainProgramDLL + "] has been loaded, " + programCount.ToString() + " plugin(s) loaded"); registry.LocateCommands(); //msg(MessageHandler.Destinations.DEST_LOCAL, UUID.Zero, "Commands found: " + registry.Cmds.Count.ToString()); GroupsCache = new Dictionary(); ReloadGroupsCache(); } catch (Exception E) { string Msg = E.Message; string STACK = E.StackTrace.Replace("ZNI", ""); Msg = Msg.Replace("ZNI", ""); Log.info(true, "Generic Exception Caught: " + Msg + " [0x0A]"); int i; int* ptr = &i; IntPtr addr = (IntPtr)ptr; MessageFactory.Post(Destinations.DEST_LOCAL, "Generic Exception Caught: " + Msg + " [0x0A, 0x" + addr.ToString("x") + "]\nSTACK: " + STACK, UUID.Zero); } if (File.Exists("XUP")) { File.Delete("XUP"); MessageFactory.Post(Destinations.DEST_LOCAL, $"Updated to version {BotStr} - {BotVer}", UUID.Zero); } } foreach (IProgram plugin in g_ZPrograms) { plugin.getTick(); // Trigger a tick event!!! } //MasterObjectCaches.Save(); if (startupSeq) startupSeq = false; if(BotSession.Instance.LaunchTime.AddHours(MainConfiguration.Instance.AutoRelogAfterHours) < DateTime.Now) { // Initiate a relog try { prompter.Interrupt(); prompter.Abort(); }catch(Exception e) { client.Self.Chat(e.Message, 0, ChatType.Normal); } client.Self.Chat("Automatic relog in progress", 0, ChatType.Whisper); g_iIsRunning = false; client.Network.Logout(); } //if (MasterObjectCaches.RegionPrims.Count == 0 && client.Network.Connected) //{ // onSimChange(null, new SimChangedEventArgs(client.Network.CurrentSim)); //} if (BotSession.Instance.EnqueueExit) g_iIsRunning = false; if (BotSession.Instance.EnqueueGroupRefresh) { BotSession.Instance.EnqueueGroupRefresh = false; ReloadGroupsCache(); } BotSession.Instance.MSGSVC.PopMessage(); } prompter.Interrupt(); client.Network.Logout(); } while (client.Network.Connected) { } if (BotSession.Instance.WaitForFiveMinutes) { AutoResetEvent are = new AutoResetEvent(false); are.WaitOne(TimeSpan.FromMinutes(5)); } File.Delete("PID.lock"); Environment.Exit(0); //System.Console.WriteLine("PAUSING. PRESS ANY KEY TO EXIT"); //System.Console.ReadKey(); } private static ManualResetEvent GroupJoinWaiter = new ManualResetEvent(false); private static void MSGSVC_onGroupMessage(object sender, MessageEventArgs e) { // not implemented, yet, but do not throw error switch (e.Msg.GetMessageSource()) { case Destinations.DEST_GROUP: BotSession.Instance.grid.Self.InstantMessageGroup(e.Msg.GetTarget(), e.Msg.GetMessage()); break; default: return; } } private static void MSGSVC_onIM(object sender, MessageEventArgs e) { switch (e.Msg.GetMessageSource()) { case Destinations.DEST_AGENT: BotSession.Instance.grid.Self.InstantMessage(e.Msg.GetTarget(), e.Msg.GetMessage()); break; default: return; } } private static void MSGSVC_onChat(object sender, MessageEventArgs e) { switch (e.Msg.GetMessageSource()) { case Destinations.DEST_LOCAL: BotSession.Instance.grid.Self.Chat(e.Msg.GetMessage(), e.Msg.GetChannel(), ChatType.Normal); break; default: return; } } private static void onJoinGroupChat(object sender, GroupChatJoinedEventArgs e) { if (e.Success) GroupJoinWaiter.Set(); } private static AutoResetEvent ReqObjProperties = new AutoResetEvent(false); private static Dictionary ReqObjPropertiesData = new Dictionary(); [STAThread()] private static void onObjectUpdate(object sender, PrimEventArgs e) { //Console.WriteLine("ObjectUpdate @ " + DateTime.Now); /* * Disabled until Libremetaverse is fully tested * while (Monitor.IsEntered(_CacheLock)) { } lock (_CacheLock) { if (MasterObjectCaches == null) { MasterObjectCaches = ObjectCaches.Instance; Console.WriteLine("\n=> Recv: ObjectUpdate; Set: new MasterObjectCache(" + e.Simulator.Name + ")"); } if (MasterObjectCaches.RegionPrims == null) MasterObjectCaches.RegionPrims = new Dictionary>(); Dictionary NewDictionary = new Dictionary(); if (!MasterObjectCaches.RegionPrims.ContainsKey(e.Simulator.Name)) { NewDictionary = new Dictionary(); try { MasterObjectCaches.RegionPrims.Add(e.Simulator.Name, NewDictionary); MasterObjectCaches.MarkDirty(); } catch (Exception E) { Console.WriteLine("FAILED TO INITIALIZE MASTER OBJECT CACHE FOR REGION"); Console.WriteLine(E.StackTrace); } } else { NewDictionary = MasterObjectCaches.RegionPrims[e.Simulator.Name]; } Primitive p = e.Prim; if (!NewDictionary.ContainsKey(e.Prim.ID)) { NewDictionary.Add(p.ID, new Primitive2(p)); MasterObjectCaches.RegionPrims[e.Simulator.Name] = NewDictionary; MasterObjectCaches.MarkDirty(); // Check properties val if (p.Properties == null) { client.Objects.SelectObject(client.Network.CurrentSim, p.LocalID); client.Objects.DeselectObject(client.Network.CurrentSim, p.LocalID); } if (p.OwnerID == client.Self.AgentID) { Console.WriteLine("[!] Discovered a prim that i created\n\n"); } } else { // Prim is already in list. // Verify that the properties are still the same if (p.Properties == null) { client.Objects.SelectObject(client.Network.CurrentSim, p.LocalID); client.Objects.DeselectObject(client.Network.CurrentSim, p.LocalID); } } } */ } private ManualResetEvent profile_get = new ManualResetEvent(false); private Avatar.AvatarProperties Properties_AV; [CommandGroup("set_profile_text", 6, "set_profile_text [text:Base64] - Sets the profile text", Destinations.DEST_AGENT | Destinations.DEST_LOCAL)] public void setProfileText(UUID client, int level, string[] additionalArgs, Destinations source, UUID agentKey, string agentName) { MHE(source, client, "Setting..."); BotSession.Instance.grid.Avatars.AvatarPropertiesReply += Avatars_AvatarPropertiesReply; BotSession.Instance.grid.Avatars.RequestAvatarProperties(BotSession.Instance.grid.Self.AgentID); profile_get.Reset(); if (profile_get.WaitOne(TimeSpan.FromSeconds(30))) { Properties_AV.AboutText = Encoding.UTF8.GetString(Convert.FromBase64String(additionalArgs[0])); BotSession.Instance.grid.Self.UpdateProfile(Properties_AV); MHE(source, client, "Profile text set"); } else { MHE(source, client, "The profile text could not be set. Timeout experienced"); BotSession.Instance.grid.Avatars.AvatarPropertiesReply -= Avatars_AvatarPropertiesReply; } } private void Avatars_AvatarPropertiesReply(object sender, AvatarPropertiesReplyEventArgs e) { Properties_AV = e.Properties; profile_get.Set(); BotSession.Instance.grid.Avatars.AvatarPropertiesReply -= Avatars_AvatarPropertiesReply; } [STAThread()] private static void onObjectTerseUpdate(object sender, TerseObjectUpdateEventArgs e) { //Console.WriteLine("TerseObjectUpdate @ " + DateTime.Now); PrimEventArgs ex = new PrimEventArgs(e.Simulator, e.Prim, e.TimeDilation, false, false); onObjectUpdate(sender, ex); } [STAThread()] private static void onObjectProperties(object sender, ObjectPropertiesEventArgs e) { //Console.WriteLine("ObjectProperties @ " + DateTime.Now); //Console.WriteLine("\n=> Got prim properties <=\n"); /* Dictionary PrimList = MasterObjectCaches.RegionPrims[e.Simulator.Name]; UUID id = e.Properties.ObjectID; if (PrimList.ContainsKey(id)) { Primitive2 prim = PrimList[id]; if (prim.Properties != new Primitive2Properties(e.Properties)) { prim.Properties = new Primitive2Properties(e.Properties); PrimList[id] = prim; MasterObjectCaches.RegionPrims[e.Simulator.Name] = PrimList; MasterObjectCaches.MarkDirty(); } } else { // Skip. There is nothing we can do }*/ //ReqObjPropertiesData.Add(e.Properties.ObjectID, e.Properties); // This function is disabled until LibreMetaverse is fully tested //ReqObjProperties.Set(); } private static void onSimChange(object sender, SimChangedEventArgs e) { // Request object data for all prims on sim! //Dictionary simPrims = client.Network.CurrentSim.ObjectsPrimitives.Copy(); //ManualResetEvent mreWaiter = new ManualResetEvent(false); //mreWaiter.Reset(); //foreach(KeyValuePair kvp in simPrims) //{ // onObjectUpdate(null, new PrimEventArgs(client.Network.CurrentSim, kvp.Value, 0, false, false)); // mreWaiter.WaitOne(TimeSpan.FromMilliseconds(500)); //} } private static void onChatRecv(object sender, ChatEventArgs e) { if (e.Message == "" || e.Message == "typing") return; string eMe = e.Message; Dictionary dstuf = new Dictionary(); //Log.debugf(true, "onChatRecv", new[] { e.Message }); dstuf.Add("type", "chat"); string SRC = ""; if (e.SourceType == ChatSourceType.Agent) SRC = "agent"; else if (e.SourceType == ChatSourceType.Object) SRC = "obj"; else if (e.SourceType == ChatSourceType.System) SRC = "sys"; dstuf.Add("source", SRC); dstuf.Add("request", eMe); dstuf.Add("from", e.SourceID.ToString()); dstuf.Add("from_sess", ""); dstuf.Add("fromName", e.FromName); passArguments(JsonConvert.SerializeObject(dstuf)); //Log.debugf(false, "onChatRecv", new[] { "" }); } public static void onIMEvent(object sender, InstantMessageEventArgs e) { if (e.IM.FromAgentID == client.Self.AgentID) return; MainConfiguration mem = MainConfiguration.Instance; UUID SentBy = e.IM.FromAgentID; int Level = 0; if (mem.BotAdmins.ContainsKey(SentBy)) Level = mem.BotAdmins[SentBy]; if (e.IM.Dialog == InstantMessageDialog.GroupInvitation) { if (Level >= 4) { client.Self.GroupInviteRespond(e.IM.FromAgentID, e.IM.IMSessionID, true); } else { client.Self.GroupInviteRespond(e.IM.FromAgentID, e.IM.IMSessionID, false); MH(Destinations.DEST_AGENT, e.IM.FromAgentID, "You lack the proper permissions to perform this action"); } } else if (e.IM.Dialog == InstantMessageDialog.FriendshipOffered) { if (Level >= 4) { client.Friends.AcceptFriendship(e.IM.FromAgentID, e.IM.IMSessionID); MH(Destinations.DEST_AGENT, e.IM.FromAgentID, "Welcome to my friends list!"); } else { MH(Destinations.DEST_AGENT, e.IM.FromAgentID, "You lack proper permission"); } } else if (e.IM.Dialog == InstantMessageDialog.RequestTeleport) { if (Level >= 3) { client.Self.TeleportLureRespond(e.IM.FromAgentID, e.IM.IMSessionID, true); MH(Destinations.DEST_AGENT, e.IM.FromAgentID, "Teleporting..."); } else { client.Self.TeleportLureRespond(e.IM.FromAgentID, e.IM.IMSessionID, false); MH(Destinations.DEST_AGENT, e.IM.FromAgentID, "You lack permission"); } } else if (e.IM.Dialog == InstantMessageDialog.MessageFromObject) { if (Level >= 5) { // For this to work the object must have been granted auth!!!!! Dictionary args = new Dictionary(); args.Add("type", "im"); args.Add("source", "obj"); args.Add("request", e.IM.Message); args.Add("from", e.IM.FromAgentID.ToString()); args.Add("from_sess", e.IM.IMSessionID.ToString()); args.Add("fromName", e.IM.FromAgentName); passArguments(JsonConvert.SerializeObject(args)); } else { // If auth is insufficient, ignore it. } } else if (e.IM.Dialog == InstantMessageDialog.MessageFromAgent || e.IM.Dialog == InstantMessageDialog.SessionSend) { //if (e.IM.Message.Substring(0, 1) != "!") return; string msgs = e.IM.Message; //string msgs = e.IM.Message.Substring(1); // Perform a few tests before live deployment if (IsGroup(e.IM.IMSessionID)) { Dictionary args = new Dictionary(); args.Add("type", "group"); args.Add("source", "agent"); args.Add("request", msgs); args.Add("from", e.IM.FromAgentID.ToString()); args.Add("from_sess", e.IM.IMSessionID.ToString()); args.Add("fromName", e.IM.FromAgentName); passArguments(JsonConvert.SerializeObject(args)); } else { Dictionary args = new Dictionary(); args.Add("type", "im"); args.Add("source", "agent"); args.Add("request", msgs); args.Add("from", e.IM.FromAgentID.ToString()); args.Add("from_sess", ""); args.Add("fromName", e.IM.FromAgentName); passArguments(JsonConvert.SerializeObject(args)); } } } private static void CacheGroupRoles(object sender, GroupRolesDataReplyEventArgs e) { //MHE(MessageHandler.Destinations.DEST_LOCAL, UUID.Zero, "[debug] role_reply"); if (!Directory.Exists("zGroupCache")) Directory.CreateDirectory("zGroupCache"); // this should be purged at every bot restart!!! //MHE(MessageHandler.Destinations.DEST_LOCAL, UUID.Zero, "[debug] generating groupcache file"); zGroupCaches newCache = new zGroupCaches(); zGroupCaches.GroupMemoryData gmd = new zGroupCaches.GroupMemoryData(); foreach (KeyValuePair roleData in e.Roles) { gmd.roleID = roleData.Value.ID; gmd.RoleName = roleData.Value.Name; gmd.Title = roleData.Value.Title; gmd.Powers = roleData.Value.Powers; newCache.GMD.Add(gmd); } newCache.GroupID = e.GroupID; newCache.Save(e.GroupID.ToString()); RoleReply.Set(); FileInfo fi = new FileInfo("GroupCache/" + e.GroupID.ToString() + ".json"); //MHE(MessageHandler.Destinations.DEST_LOCAL, UUID.Zero, "[debug] Roles for secondlife:///app/group/" + e.GroupID.ToString() + "/about have been saved to: GroupCache/" + e.GroupID.ToString() + ".bdf\nFileSize: "+fi.Length.ToString(), 55); } private static Dictionary GroupsCache = null; private static ManualResetEvent GroupsEvent = new ManualResetEvent(false); private static ManualResetEvent RoleReply = new ManualResetEvent(false); private static void Groups_CurrentGroups(object sender, CurrentGroupsEventArgs e) { if (null == GroupsCache) GroupsCache = e.Groups; else lock (GroupsCache) { GroupsCache = e.Groups; } GroupsEvent.Set(); foreach (KeyValuePair DoCache in GroupsCache) { bool Retry = true; int count = 0; while (Retry) { client.Groups.RequestGroupRoles(DoCache.Value.ID); if (RoleReply.WaitOne(TimeSpan.FromSeconds(30), false)) { Retry = false; } else { count++; //MH.callbacks(MessageHandler.Destinations.DEST_LOCAL, UUID.Zero, "There appears to have been a failure requesting the group roles for secondlife:///app/group/" + DoCache.Value.ID.ToString() + "/about - Trying again"); if(count >= 5) { MH(Destinations.DEST_LOCAL, UUID.Zero, "Aborting group refresh attempt. Too many errors - Resetting cache and retrying"); GroupsEvent.Reset(); GroupsCache = new Dictionary(); client.Groups.CurrentGroups -= Groups_CurrentGroups; ReloadGroupsCache(); return; } } } } } private static void ReloadGroupsCache() { client.Groups.CurrentGroups += Groups_CurrentGroups; client.Groups.RequestCurrentGroups(); GroupsEvent.WaitOne(10000, false); client.Groups.CurrentGroups -= Groups_CurrentGroups; GroupsEvent.Reset(); } private UUID GroupName2UUID(String groupName) { UUID tryUUID; if (UUID.TryParse(groupName, out tryUUID)) return tryUUID; if (null == GroupsCache) { ReloadGroupsCache(); if (null == GroupsCache) return UUID.Zero; } lock (GroupsCache) { if (GroupsCache.Count > 0) { foreach (Group currentGroup in GroupsCache.Values) if (currentGroup.Name.ToLower() == groupName.ToLower()) return currentGroup.ID; } } return UUID.Zero; } private static bool IsGroup(UUID grpKey) { // For use in IMs since it appears partially broken at the moment return GroupsCache.ContainsKey(grpKey); } } }