Example #1
0
 /// <summary>
 /// Callback for when this bot gets disconnected, attempting to connect again in 5 minutes.
 /// </summary>
 /// <param name="sender">Sender object</param>
 /// <param name="e">Arguments for the disconnected event</param>
 /// <remarks>rewrote to show message</remarks>
 void Network_OnDisconnected(object?sender, DisconnectedEventArgs e)
 {
     if (e.Reason != NetworkManager.DisconnectType.ClientInitiated)
     {
         myStatus = Status.Reconnecting;
         DebugUtilities.WriteWarning($"{sessionid.ToString()} was disconnected ({e.Message.ToString()}), but I'm logging back in again in 5 minutes.");
         ReloginTimer.Stop();
         ReloginTimer.Interval = 5 * 60 * 1000;
         ReloginTimer.Start();
     }
 }
Example #2
0
        /// <summary>
        /// Handler event for this plugin.
        /// </summary>
        /// <param name="b">A currently active RestBot</param>
        /// <param name="Parameters">A dictionary containing the group UUID and the message to send to group IM</param>
        /// <returns>XML with information on the sent group IM message, if successful;
        /// XML error otherwise</returns>
        public override string Process(RestBot b, Dictionary <string, string> Parameters)
        {
            UUID   groupUUID;
            string message;

            try
            {
                bool check = false;
                if (Parameters.ContainsKey("key"))
                {
                    check = UUID.TryParse(Parameters["key"].ToString().Replace("_", " "), out groupUUID);
                }
                else
                {
                    return("<error>arguments: no key</error>");
                }
                if (check)
                {
                    if (Parameters.ContainsKey("message"))
                    {
                        message = Parameters["message"].ToString().Replace("%20", " ").Replace("+", " ");
                    }
                    else
                    {
                        return("<error>arguments: no message</error>");
                    }
                }
                else
                {
                    return("<error>parsekey</error>");
                }

                message = message.TrimEnd();
                if (message.Length > 1023)
                {
                    message = message.Remove(1023);
                    DebugUtilities.WriteDebug(session + " " + MethodName + " Message truncated at 1024 characters");
                }

                string response = sendIMGroup(b, groupUUID, message);

                if (string.IsNullOrEmpty(response))
                {
                    return("<error>group message not sent, or answer was empty</error>");
                }

                return("<message>" + response.Trim() + "</message>");
            }
            catch (Exception e)
            {
                DebugUtilities.WriteError(e.Message);
                return("<error>loads of errors</error>");
            }
        }
Example #3
0
 /// <summary>
 /// StatefulPlugins stuff
 /// </summary>
 /// <param name="defn">List of plugin definitions</param>
 public static void AddStatefulPluginDefinition(Type defn)
 {
     lock (StatefulPluginDefinitions)
     {
         DebugUtilities.WriteDebug($"Plugin definition: {defn.FullName}");
         if (defn.IsSubclassOf(typeof(StatefulPlugin)))
         {
             StatefulPluginDefinitions.Add(defn);
         }
     }
 }
Example #4
0
 void Self_GroupChatJoined(object?sender, GroupChatJoinedEventArgs e)
 {
     if (e.Success)
     {
         DebugUtilities.WriteInfo(session.ToString() + " " + MethodName + "Joined {0} Group Chat Success!");
         WaitForSessionStart.Set();
     }
     else
     {
         DebugUtilities.WriteInfo(session.ToString() + " " + MethodName + "Join Group Chat failed :(");
     }
 }
Example #5
0
 Process(RestBot b, Dictionary <string, string> Parameters)
 {
     try
     {
         return($"<{MethodName}><CurrentSim>{b.Client.Network.CurrentSim.ToString()}</CurrentSim><Position>{b.Client.Self.SimPosition.X},{b.Client.Self.SimPosition.Y},{b.Client.Self.SimPosition.Z}</Position></{MethodName}>");
     }
     catch (Exception e)
     {
         DebugUtilities.WriteError(e.Message);
         return($"<error>{MethodName}: {e.Message}</error>");
     }
 }
Example #6
0
        Process(RestBot b, Dictionary <string, string> Parameters)
        {
            uint
                regionX,
                regionY;

            Utils
            .LongToUInts(b.Client.Network.CurrentSim.Handle,
                         out regionX,
                         out regionY);

            try
            {
                string target = String.Empty;

                if (Parameters.ContainsKey("target"))
                {
                    target =
                        Parameters["target"]
                        .ToString()
                        .Replace("%20", " ")
                        .Replace("+", " ");
                }
                else
                {
                    return($"<error>{MethodName}: missing argument for target</error>");
                }

                if (target.Length == 0 || target == "off")
                {
                    Active        = false;
                    targetLocalID = 0;
                    b.Client.Self.AutoPilotCancel();
                    return($"<{MethodName}>off</{MethodName}>");
                }
                else
                {
                    if (Follow(target))
                    {
                        return($"<{MethodName}>on</{MethodName}>");
                    }
                    else
                    {
                        return($"<error>cannot follow {target}</error>");
                    }
                }
            }
            catch (Exception e)
            {
                DebugUtilities.WriteError(e.Message);
                return($"<error>{MethodName}: {e.Message}</error>");
            }
        }
Example #7
0
        }         // end getName()

        /// <summary>
        /// Loop through all (pending) replies for UUID/Avatar names
        /// and process them if they contain any key we're looking for.
        /// </summary>
        /// <param name="sender">parameter ignored</param>
        /// <param name="e">List of UUID/Avatar names</param>
        /// <returns>void</returns>
        /// <remarks>using new Directory functionality</remarks>
        public static void Avatars_OnDirPeopleReply(
            object?sender,
            DirPeopleReplyEventArgs e
            )
        {
            if (e.MatchedPeople.Count < 1)
            {
                DebugUtilities
                .WriteWarning("Avatars_OnDirPeopleReply() - Error: empty people directory reply");
            }
            else
            {
                int replyCount = e.MatchedPeople.Count;

                DebugUtilities
                .WriteInfo("Avatars_OnDirPeopleReply() - Processing " +
                           replyCount.ToString() +
                           " DirPeople replies");
                for (int i = 0; i < replyCount; i++)
                {
                    string avatarName =
                        e.MatchedPeople[i].FirstName + " " + e.MatchedPeople[i].LastName;
                    UUID avatarKey = e.MatchedPeople[i].AgentID;
                    DebugUtilities
                    .WriteDebug("Avatars_OnDirPeopleReply() -  Reply " +
                                (i + 1).ToString() +
                                " of " +
                                replyCount.ToString() +
                                " Key : " +
                                avatarKey.ToString() +
                                " Name : " +
                                avatarName);

                    if (!avatarKeys.ContainsKey(avatarName))
                    {
                        /* || avatarKeys[avatarName] == null )	 // apparently dictionary entries cannot be null */
                        lock (avatarKeys)
                        {
                            avatarKeys[avatarName.ToLower()] = avatarKey;
                        }
                    }

                    lock (KeyLookupEvents)
                    {
                        if (KeyLookupEvents.ContainsKey(avatarName.ToLower()))
                        {
                            KeyLookupEvents[avatarName.ToLower()].Set();
                            DebugUtilities.WriteDebug(avatarName.ToLower() + " KLE set!");
                        }
                    }
                }
            }
        }         // end Avatars_OnDirPeopleReply()
Example #8
0
 Process(RestBot b, Dictionary <string, string> Parameters)
 {
     try
     {
         b.Client.Self.Stand();
         return($"<{MethodName}>standing</{MethodName}>");
     }
     catch (Exception e)
     {
         DebugUtilities.WriteError(e.Message);
         return($"<error>{MethodName}: {e.Message}</error>");
     }
 }
Example #9
0
 /// <summary>Initialisation</summary>
 public override void Initialize(RestBot bot)
 {
     session = bot.sessionid;
     // double-checking this, because I really, really want to force a configuration override to turn this off!
     // (gwyneth 20220412)
     if (Program.config != null && Program.config.plugin.reaper == true)
     {
         DebugUtilities.WriteDebug($"{session} {MethodName} startup");
         Reaper.Init(); //start up the reaper if we havent already (the check to see if we have is in this function)
     }
     else
     {
         DebugUtilities.WriteDebug(session + " REAPER not starting due to configuration override");
     }
 }
Example #10
0
        /// <summary>
        /// name2key (avatar name to UUID)
        /// </summary>
        /// <param name="b">RESTbot object</param>
        /// <param name="name">Name of avatar to check</param>
        /// <returns>UUID of corresponding avatar, if it exists</returns>
        public UUID getKey(RestBot b, String name)
        {
            DebugUtilities
            .WriteInfo($"{session} {MethodName} Looking up key for {name}");
            name = name.ToLower();
            DebugUtilities.WriteDebug($"Looking up: {name}");
            DebugUtilities
            .WriteDebug("Key not in cache, requesting directory lookup");
            lock (KeyLookupEvents)
            {
                KeyLookupEvents.Add(name, new AutoResetEvent(false));
            }
            DebugUtilities
            .WriteDebug($"Lookup Event added, KeyLookupEvents now has a total of {KeyLookupEvents.Count.ToString()} entries");
            DirFindQueryPacket find = new DirFindQueryPacket();

            find.AgentData.AgentID    = b.Client.Self.AgentID;          // was Network and not Self
            find.AgentData.SessionID  = b.Client.Self.SessionID;
            find.QueryData.QueryFlags = 1;

            //find.QueryData.QueryText = Helpers.StringToField(name);
            find.QueryData.QueryText  = Utils.StringToBytes(name);
            find.QueryData.QueryID    = new UUID("00000000000000000000000000000001");
            find.QueryData.QueryStart = 0;

            b.Client.Network.SendPacket((Packet)find);
            DebugUtilities
            .WriteDebug($"Packet sent - KLE has {KeyLookupEvents.Count.ToString()} entries... now waiting");
            KeyLookupEvents[name].WaitOne(15000, true);
            DebugUtilities.WriteDebug("Waiting done!");
            lock (KeyLookupEvents)
            {
                KeyLookupEvents.Remove(name);
            }
            DebugUtilities
            .WriteDebug($"Done with KLE, now has {KeyLookupEvents.Count.ToString()} entries");
            UUID response = new UUID();

            if (avatarKeys.ContainsKey(name))
            {
                response = avatarKeys[name];
                lock (avatarKeys)
                {
                    avatarKeys.Remove(name);
                }
            }
            return(response);
        }
Example #11
0
        public override string Process(RestBot b, Dictionary <string, string> Parameters)
        {
            try
            {
                string type   = String.Empty;
                bool   check  = true;
                float  radius = 0.0f;

                if (Parameters.ContainsKey("type"))
                {
                    type = Parameters["type"].ToString().Replace("+", " ");
                }
                else
                {
                    check = false;
                }

                if (Parameters.ContainsKey("radius"))
                {
                    check &= float.TryParse(Parameters["radius"], out radius);
                }
                else
                {
                    check = false;
                }

                if (!check)
                {
                    return("<error>parameters have to be type, radius</error>");
                }

                // *** get current location ***
                Vector3 location = b.Client.Self.SimPosition;

                Primitive found = b.Client.Network.CurrentSim.ObjectsPrimitives.Find(
                    delegate(Primitive prim) {
                    return(prim.Properties.Name == type);
                });


                return($"<nearby_prim><pos>{found.Position.X},{found.Position.Y},{found.Position.Z}</pos></nearby_prim>");
            }
            catch (Exception e)
            {
                DebugUtilities.WriteError(e.Message);
                return($"<error>{MethodName}: {e.Message}</error>");
            }
        }
Example #12
0
 Process(RestBot b, Dictionary <string, string> Parameters)
 {
     try
     {
         return(String
                .Format("<position>{0},{1},{2}</position>",
                        b.Client.Self.SimPosition.X,
                        b.Client.Self.SimPosition.Y,
                        b.Client.Self.SimPosition.Z));
     }
     catch (Exception e)
     {
         DebugUtilities.WriteError(e.Message);
         return($"<error>{e.Message}</error>");
     }
 }
Example #13
0
        /// <summary>
        /// Handler event for this plugin.
        /// </summary>
        /// <param name="b">A currently active RestBot</param>
        /// <param name="Parameters">A dictionary containing the group name, or UUID</param>
        /// <returns>XML containing the group name that was activated, if successful; XML error otherwise.</returns>
        public override string Process(RestBot b, Dictionary <string, string> Parameters)
        {
            UUID   groupUUID;
            string groupName;

            DebugUtilities.WriteDebug("Entering group key parser");
            try
            {
                if (Parameters.ContainsKey("name"))
                {
                    groupName = Parameters["name"].ToString().Replace("%20", " ").Replace("+", " ");
                }
                else
                {
                    return($"<error>{MethodName}: arguments</error>");
                }
                DebugUtilities.WriteDebug("Activating group");

                groupUUID = GroupName2UUID(b, groupName);
                if (UUID.Zero != groupUUID)
                {
                    string response = activateGroup(b, groupUUID);
                    DebugUtilities.WriteDebug("Complete");
                    if (response != null)
                    {
                        return($"<active>{response.Trim()}</active>");
                    }
                    else
                    {
                        return($"<error>{MethodName}: group could not be activated</error>");
                    }
                }
                else
                {
                    DebugUtilities.WriteDebug($"Error: group {groupName} doesn't exist");
                    return($"<error>{MethodName}: group name '{groupName}' doesn't exist.</error>");
                }
            }
            catch (Exception e)
            {
                DebugUtilities.WriteError(e.Message);
                return($"<error>{MethodName}: parsekey</error>");
            }
        }
Example #14
0
        /*
         * // obsoleted packet call
         * public void Avatars_OnDirPeopleReply(Packet packet, Simulator simulator)
         * {
         *      DirPeopleReplyPacket reply = (DirPeopleReplyPacket)packet;
         *      DebugUtilities.WriteDebug("Got DirPeopleReply!");
         *      if (reply.QueryReplies.Length < 1) {
         *              DebugUtilities.WriteWarning(session + " {MethodName + " Error - empty people directory reply");
         *      } else {
         *              int replyCount = reply.QueryReplies.Length;
         *              DebugUtilities.WriteInfo(session + " {MethodName + " Proccesing {replyCount.ToString() + " DirPeople replies");
         *              for ( int i = 0 ; i <  replyCount ; i++ ) {
         *                      string avatarName = Utils.BytesToString(reply.QueryReplies[i].FirstName) + " {Utils.BytesToString(reply.QueryReplies[i].LastName);
         *                      UUID avatarKey = reply.QueryReplies[i].AgentID;
         *                      DebugUtilities.WriteDebug(session + " {MethodName + " Reply {(i + 1).ToString() + " of {replyCount.ToString() + " Key : {avatarKey.ToString() + " Name : {avatarName);
         *
         *                      if ( !avatarKeys.ContainsKey(avatarName) ) // || avatarKeys[avatarName] == null ) { // apparently dictionary entries cannot be null
         *                              lock ( avatarKeys ) {
         *                                      avatarKeys[avatarName.ToLower()] = avatarKey;
         *                              }
         *                      }
         *
         *                      lock(KeyLookupEvents)
         *                      {
         *                               if ( KeyLookupEvents.ContainsKey(avatarName.ToLower())) {
         *                                               KeyLookupEvents[avatarName.ToLower()].Set();
         *                                      DebugUtilities.WriteDebug(avatarName.ToLower() + " KLE set!");
         *                               }
         *                      }
         *              }
         *      }
         * } */
        /// <summary>
        /// Loop through all (pending) replies for UUID/Avatar names
        /// and process them if they contain any key we're looking for.
        /// </summary>
        /// <param name="sender">parameter ignored</param>
        /// <param name="e">List of UUID/Avatar names</param>
        /// <returns>void</returns>
        /// <remarks>using new Directory functionality</remarks>
        public void Avatars_OnDirPeopleReply(
            object?sender,
            DirPeopleReplyEventArgs e
            )
        {
            if (e.MatchedPeople.Count < 1)
            {
                DebugUtilities
                .WriteWarning($"{session} {MethodName} Error - empty people directory reply");
            }
            else
            {
                int replyCount = e.MatchedPeople.Count;

                DebugUtilities
                .WriteInfo($"{session} {MethodName} Processing {replyCount.ToString()} DirPeople replies");
                for (int i = 0; i < replyCount; i++)
                {
                    string avatarName = e.MatchedPeople[i].FirstName + e.MatchedPeople[i].LastName;
                    UUID   avatarKey  = e.MatchedPeople[i].AgentID;
                    DebugUtilities
                    .WriteDebug($"{session} {MethodName} Reply {(i + 1).ToString()} of {replyCount.ToString()} Key: {avatarKey.ToString()} Name: {avatarName}");

                    if (!avatarKeys.ContainsKey(avatarName))
                    {
                        /* || avatarKeys[avatarName] == null )	 // apparently dictionary entries cannot be null */
                        lock (avatarKeys)
                        {
                            avatarKeys[avatarName.ToLower()] = avatarKey;
                        }
                    }

                    lock (KeyLookupEvents)
                    {
                        if (KeyLookupEvents.ContainsKey(avatarName.ToLower()))
                        {
                            KeyLookupEvents[avatarName.ToLower()].Set();
                            DebugUtilities.WriteDebug($"{avatarName.ToLower()} KLE set!");
                        }
                    }
                }
            }
        }
Example #15
0
        Process(RestBot b, Dictionary <string, string> Parameters)
        {
            /// <summary>UUID for the prim/object that we intend the bot to touch</summary>
            UUID touchTargetID = UUID.Zero;

            DebugUtilities.WriteDebug($"{b.sessionid} {MethodName} - Searching for prim to touch");
            try
            {
                bool check = false;
                if (Parameters.ContainsKey("prim"))
                {
                    check =
                        UUID
                        .TryParse(Parameters["prim"].ToString().Replace("_", " "),
                                  out touchTargetID);
                }

                if (!check)
                {
                    return("<error>prim to touch not specified</error>");
                }

                // If we get to this point means that we have a correctly parsed key for the target prim
                DebugUtilities.WriteDebug($"{b.sessionid} {MethodName} - Trying to touch {touchTargetID.ToString()}...");

                Primitive targetPrim = b.Client.Network.CurrentSim.ObjectsPrimitives.Find(
                    prim => prim.ID == touchTargetID
                    );

                if (targetPrim != null)
                {
                    b.Client.Self.Touch(targetPrim.LocalID);
                    return($"<{MethodName}>touching {targetPrim.ID.ToString()} ({targetPrim.LocalID})</{MethodName}>");
                }

                return($"<error>no prim with UUID {touchTargetID} found</error>");
            }
            catch (Exception e)
            {
                DebugUtilities.WriteError(e.Message);
                return($"<error>{e.Message}</error>");
            }
        }
Example #16
0
        /// <summary>
        /// Handler event for this plugin.
        /// </summary>
        /// <param name="b">A currently active RestBot</param>
        /// <param name="Parameters">A dictionary containing the group UUID</param>
        /// <returns>XML with information on the activated group key if successful,
        /// XML error otherwise</returns>
        public override string Process(RestBot b, Dictionary <string, string> Parameters)
        {
            UUID groupUUID;

            DebugUtilities.WriteDebug("Entering group key parser");
            try
            {
                bool check = false;
                if (Parameters.ContainsKey("key"))
                {
                    DebugUtilities.WriteDebug("Attempting to parse from POST");
                    check = UUID.TryParse(Parameters["key"].ToString().Replace("_", " "), out groupUUID);
                    DebugUtilities.WriteDebug("Succesfully parsed POST");
                }
                else
                {
                    return($"<error>{MethodName}: invalid arguments</error>");
                }
                if (check)
                {
                    DebugUtilities.WriteDebug("Activating group");
                    string?response = activateGroup(b, groupUUID);
                    DebugUtilities.WriteDebug("Complete");
                    if (response != null)
                    {
                        return($"<active>{response.Trim()}</active>");
                    }
                    else
                    {
                        return($"<error>{MethodName}: group could not be activated</error>");
                    }
                }
                else
                {
                    return($"<error>{MethodName}: parsekey</error>");
                }
            }
            catch (Exception e)
            {
                DebugUtilities.WriteError(e.Message);
                return($"<error>{MethodName}: parsekey</error>");
            }
        }
Example #17
0
        }         // end Avatars_OnAvatarNames()

        /// <summary>
        /// key2name (given an avatar UUID, returns the avatar name, if it exists)
        /// </summary>
        /// <param name="b">RESTbot object</param>
        /// <param name="key">UUID of avatar to check</param>
        /// <returns>Name of the avatar if it exists; String.Empty if not</returns>
        public static string getName(RestBot b, UUID id)
        {
            DebugUtilities
            .WriteInfo("getName(): Looking up name for " + id.ToString());
            b.Client.Avatars.UUIDNameReply += Avatars_OnAvatarNames;
            lock (NameLookupEvents)
            {
                NameLookupEvents.Add(id, new AutoResetEvent(false));
            }

            b.Client.Avatars.RequestAvatarName(id);

            if (!NameLookupEvents[id].WaitOne(15000, true))
            {
                DebugUtilities
                .WriteWarning("getName(): timed out on avatar name lookup");
            }
            lock (NameLookupEvents)
            {
                NameLookupEvents.Remove(id);
            }

            // C# 8+ is stricter with null assignments.
            // string? response = null;	// technically this cannot ever be null, so it doesn't make sense...
            string response = String.Empty;

            if (avatarNames.ContainsKey(id))
            {
                response = avatarNames[id];                 // .Name removed
                lock (avatarNames)
                {
                    avatarNames.Remove(id);
                }
            }

            /*          else
             * {
             *      response = String.Empty;
             * } */
            b.Client.Avatars.UUIDNameReply -= Avatars_OnAvatarNames;
            return(response);
        }         // end getName()
Example #18
0
        Process(RestBot b, Dictionary <string, string> Parameters)
        {
            UUID agentKey;

            try
            {
                bool check = false;
                if (Parameters.ContainsKey("key"))
                {
                    check =
                        UUID
                        .TryParse(Parameters["key"].ToString().Replace("_", " "),
                                  out agentKey);
                }
                else
                {
                    return("<error>arguments</error>");
                }
                if (check)
                {
                    string?response = getGroups(b, agentKey);                      // string can be null
                    if (response == null)
                    {
                        return("<error>not found</error>");
                    }
                    else
                    {
                        return(response);
                    }
                }
                else
                {
                    return("<error>unknown</error>");
                }
            }
            catch (Exception e)
            {
                DebugUtilities.WriteError(e.Message);
                return("<error>parsekey</error>");
            }
        }
Example #19
0
        Process(RestBot b, Dictionary <string, string> Parameters)
        {
            UUID agentKey;

            DebugUtilities.WriteDebug("Entering avatarname parser");
            try
            {
                bool check = false;
                if (Parameters.ContainsKey("key"))
                {
                    DebugUtilities.WriteDebug("Attempting to parse from POST");
                    check =
                        UUID
                        .TryParse(Parameters["key"].ToString().Replace("_", " "),
                                  out agentKey);
                    DebugUtilities.WriteDebug("Succesfully parsed POST");
                }
                else
                {
                    return("<error>arguments</error>");
                }
                if (check)
                {
                    DebugUtilities.WriteDebug("Parsing name");
                    string response = getName(b, agentKey);
                    DebugUtilities.WriteDebug("Parsed name");
                    DebugUtilities.WriteDebug("Complete");
                    return($"<name>{response.Trim()}</name>");
                }
                else
                {
                    return("<error>parsekey</error>");
                }
            }
            catch (Exception e)
            {
                DebugUtilities.WriteError(e.Message);
                return("<error>parsekey</error>");
            }
        }
Example #20
0
        /// <summary>
        /// key2name (given an avatar UUID, returns the avatar name, if it exists)
        /// </summary>
        /// <param name="b">RESTbot object</param>
        /// <param name="key">UUID of avatar to check</param>
        /// <returns>Name of the avatar if it exists; String.Empty if not</returns>
        private string getName(RestBot b, UUID id)
        {
            DebugUtilities
            .WriteInfo($"{session.ToString()} {MethodName} Looking up name for {id.ToString()}");
            lock (NameLookupEvents)
            {
                NameLookupEvents.Add(id, new AutoResetEvent(false));
            }

            b.Client.Avatars.RequestAvatarName(id);

            if (!NameLookupEvents[id].WaitOne(15000, true))
            {
                DebugUtilities
                .WriteWarning($"{session.ToString()} {MethodName} timed out on avatar name lookup");
            }
            lock (NameLookupEvents)
            {
                NameLookupEvents.Remove(id);
            }

            // C# 8+ is stricter with null assignments.
            // string? response = null;	// technically this cannot ever be null, so it doesn't make sense...
            string response = String.Empty;

            if (avatarNames.ContainsKey(id))
            {
                response = avatarNames[id];                 // .Name removed
                lock (avatarNames)
                {
                    avatarNames.Remove(id);
                }
            }

            /*			else
             * {
             *      response = String.Empty;
             * } */
            return(response);
        }
Example #21
0
 /// <summary>
 /// Loop through all (pending) replies for UUID/Avatar names
 /// and process them if they contain any key we're looking for.
 /// </summary>
 /// <param name="sender">parameter ignored</param>
 /// <param name="e">List of UUID/Avatar names</param>
 /// <returns>void</returns>
 /// <remarks>obsolete syntax changed</remarks>
 private void Avatars_OnAvatarNames(object?sender, UUIDNameReplyEventArgs e)
 {
     DebugUtilities.WriteDebug($"{session.ToString()} Processing {e.Names.Count.ToString()} AvatarNames replies");
     foreach (KeyValuePair <UUID, string> kvp in e.Names)
     {
         if (!avatarNames.ContainsKey(kvp.Key) || avatarNames[kvp.Key] == null)
         {
             DebugUtilities.WriteDebug($"{session.ToString()} Reply Name: {kvp.Value} Key: {kvp.Key.ToString()}");
             lock (avatarNames)
             {
                 // avatarNames[kvp.Key] = new Avatar(); // why all this trouble?
                 // FIXME: Change this to .name when we move inside libsecondlife
                 // avatarNames[kvp.Key].Name = kvp.Value; // protected
                 avatarNames[kvp.Key] = kvp.Value;
             }
             if (NameLookupEvents.ContainsKey(kvp.Key))
             {
                 NameLookupEvents[kvp.Key].Set();
             }
         }
     }
 }
Example #22
0
        DoProcessing(Dictionary <string, string> Parameters, string[] parts)
        {
            string Method      = parts[0];
            string?debugparams = null;              // must allow null (gwyneth 20220109)

            foreach (KeyValuePair <string, string> kvp in Parameters)
            {
                debugparams = $"{debugparams} [{kvp.Key}={kvp.Value}] ";
            }
            DebugUtilities.WriteDebug($"Session ID: {sessionid}, Method: {Method}, Parameters: {debugparams}");

            //Actual processing
            if (Plugins.ContainsKey(Method))
            {
                return(Plugins[Method].Process(this, Parameters));
            }
            else             //Process the stateful plugins
            if (StatefulPlugins.ContainsKey(Method))
            {
                return(StatefulPlugins[Method].Process(this, Parameters));
            }
            else if (Method == "stat")
            {
                string response = $@"<{Method}>
	<name>{Client.Self.FirstName} {Client.Self.LastName}</name>
	<key>{Client.Self.AgentID.ToString()}</key>
	<uptime>{(DateTime.Now - uptime)}</uptime>
</{Method}>
";
                return(response);
            }
            else if (Method == "status")
            {
                return($"<{Method}>{myStatus.ToString()}</{Method}>");
            }
            return("<error>novalidplugin</error>");
        } // end DoProcessing
Example #23
0
        /// <summary>
        /// Get online status of an avatar
        /// </summary>
        /// <param name="b">RESTbot object</param>
        /// <param name="key">UUID of avatar to check</param>
        /// <returns>true or false, if the avatar is or isn't online</returns>
        public bool getOnline(RestBot b, UUID key)
        {
            DebugUtilities
            .WriteInfo($"{session} {MethodName} Looking up online status for {key.ToString()}");

            lock (OnlineLookupEvents)
            {
                OnlineLookupEvents.Add(key, new AutoResetEvent(false));
            }

            // obsolete

            /*
             * AvatarPropertiesRequestPacket p = new AvatarPropertiesRequestPacket();
             * p.AgentData.AgentID = b.Client.Network.AgentID;
             * p.AgentData.SessionID = b.Client.Network.SessionID;
             * p.AgentData.AvatarID = key;
             *
             * b.Client.Network.SendPacket( (Packet) p);
             */
            b.Client.Avatars.RequestAvatarProperties(key);

            OnlineLookupEvents[key].WaitOne(15000, true);

            lock (OnlineLookupEvents)
            {
                OnlineLookupEvents.Remove(key);
            }
            bool response = avatarOnline[key];

            lock (avatarOnline)
            {
                avatarOnline.Remove(key);
            }
            return(response);
        }
Example #24
0
        /// <summary>
        /// Internal function that wil set the bot's group to a certain group UUID.
        /// </summary>
        /// <param name="b">A currently active RestBot</param>
        /// <param name="Parameters">A dictionary containing the UUID for a group.</param>
        /// <returns>String with the group name, or null if group not found</returns>
        private string?activateGroup(RestBot b, UUID groupUUID)
        {
            DebugUtilities.WriteInfo($"{session.ToString()} {MethodName} Activating group {groupUUID.ToString()}");
            EventHandler <PacketReceivedEventArgs> pcallback = AgentDataUpdateHandler;

            b.Client.Network.RegisterCallback(PacketType.AgentDataUpdate, pcallback);
            b.Client.Groups.ActivateGroup(groupUUID);

            if (!GroupsEvent.WaitOne(15000, true))
            {
                DebugUtilities.WriteWarning($"{session.ToString()} {MethodName} timed out on setting active group");
            }

            // ignore everything and just reset the event
            b.Client.Network.UnregisterCallback(PacketType.AgentDataUpdate, pcallback);
            GroupsEvent.Reset();

            if (String.IsNullOrEmpty(activeGroup))
            {
                DebugUtilities.WriteWarning($"{session.ToString()} {MethodName} Failed to activate the group {groupUUID.ToString()}");
            }

            return(activeGroup);
        }
Example #25
0
        /// <summary>
        /// Activates a group for a 'bot, given the group key.
        /// </summary>
        /// <param name="b">A currently active RestBot</param>
        /// <param name="groupUUID">UUID of the group to activate</param>
        /// <returns>Activated group name, or empty if activation failed</returns>
        private string activateGroup(RestBot b, UUID groupUUID)
        {
            DebugUtilities.WriteInfo(session.ToString() + " " + MethodName + " Activating group " + groupUUID.ToString());
            EventHandler <PacketReceivedEventArgs> pcallback = AgentDataUpdateHandler;

            b.Client.Network.RegisterCallback(PacketType.AgentDataUpdate, pcallback);
            b.Client.Groups.ActivateGroup(groupUUID);

            if (!GroupsEvent.WaitOne(15000, true))
            {
                DebugUtilities.WriteWarning(session + " " + MethodName + " timed out on setting active group");
            }

            // ignore everything and just reset the event
            b.Client.Network.UnregisterCallback(PacketType.AgentDataUpdate, pcallback);
            GroupsEvent.Reset();

            if (String.IsNullOrEmpty(activeGroup))
            {
                DebugUtilities.WriteWarning(session + " " + MethodName + " Failed to activate the group " + groupUUID);
                return("");                     // maybe we ought to return something else? (gwyneth 20220127)
            }
            return(activeGroup);                // guaranteed *not* to be null, nor empty! (gwyneth 20220127)
        }
Example #26
0
        /// <summary>
        /// getKeySimple gets an avatar's UUID key, given its (full) avatar name
        /// </summary>
        /// <param name="b">RESTbot object</param>
        /// <param name="name">Name of avatar to check</param>
        /// <returns>UUID of corresponding avatar, if it exists</returns>
        public static UUID getKeySimple(RestBot b, String name)
        {
            // add callback to handle reply
            b.Client.Avatars.AvatarPickerReply += Avatars_AvatarPickerReply;

            name = name.ToLower();

            lock (ToAvatarName)
            {
                ToAvatarName = name;
            }

            // Check if the avatar UUID is already in our cache
            if (!Name2Key.ContainsKey(name))
            {
                // Send the Query, it requires a random session ID (probably for manually killing it)
                b.Client.Avatars.RequestAvatarNameSearch(name, UUID.Random());
                // waits a reasonable amount for a reply
                NameSearchEvent.WaitOne(6000, false);
            }

            // Now we either have the key, or the avatar doesn't exist, or the network broke.
            // In all cases, we remove the callback and return whatever we've got.
            if (Name2Key.ContainsKey(name))
            {
                UUID id = Name2Key[name];
                b.Client.Avatars.AvatarPickerReply -= Avatars_AvatarPickerReply;
                return(id);
            }
            else
            {
                b.Client.Avatars.AvatarPickerReply -= Avatars_AvatarPickerReply;
                DebugUtilities.WriteDebug("$Name lookup for {name} failed, NULL_KEY returned");
                return(UUID.Zero);
            }
        }         // end getKeySimple
Example #27
0
        } = "0.0.0.0";                                                                                  // will be filled in later by Main() (gwyneth 20220425)

        /// <summary>
        /// Bootstrap method.
        /// </summary>
        /// <param name="args">Arguments passed to the application</param>
        /// <remarks>The arguments seem to get promptly ignored! (gwyneth 20220109)</remarks>
        static void Main(string[] args)
        {
            // LogManager.GetLogger(typeof(RestBot));

            // new function to parse some useful arguments and do interesting things (gwyneth 20220425)
            ParseArguments(args);

            // see if we can get the version string
            try
            {
                // Note: we ought to also extract the Assembly name, we presume it's the default (gwyneth 20220426)
#if Windows
                var fileVersionInfo = FileVersionInfo.GetVersionInfo("@RESTbot.dll");
#else
                var fileVersionInfo = FileVersionInfo.GetVersionInfo("@RESTbot");
#endif
                Version = fileVersionInfo.FileVersion + "-file";
            }
            catch (Exception e1)
            {
                // nope, this doesn't work under macOS
                DebugUtilities.WriteDebug($"Cannot retrieve file version, exception caught: {e1.Message}");
                // let's try to get the assembly name instead
                try
                {
                    var assembly = Assembly.GetExecutingAssembly();
                    Version = assembly.GetName().Version + "-assembly";
                }
                catch (Exception e2)
                {
                    // nope, that didn't work either
                    DebugUtilities.WriteDebug($"Cannot retrieve assembly version either, exception caught: {e2.Message}");
                    // finally, our last choice is trying the Informational Version
                    try
                    {
                        var assembly = Assembly.GetEntryAssembly();
                        if (assembly != null)
                        {
                            var customAttribute = assembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>();
                            if (customAttribute != null)
                            {
                                var infoVersion = customAttribute.InformationalVersion;

                                if (infoVersion != null)
                                {
                                    Version = infoVersion;
                                }
                            }
                        }
                    }
                    catch (Exception e3)
                    {
                        // we're out of luck today, we cannot even get the Informational Versoin
                        DebugUtilities.WriteDebug($"Also cannot retrieve informational version, exception caught: {e3.Message}");
                        // we'll have to stick with the hard-coded default Version instead...
                    }
                }
            }
            if (Version == null)
            {
                Version = "0.0.0.0";
            }
            DebugUtilities.WriteInfo($"RESTbot file version: {Version}");

            DebugUtilities.WriteInfo($"Reading config file '{configFile}'...");
            config = XMLConfig.Configuration.LoadConfiguration(configFile);
            if (config == null)
            {
                // configuration is mandatory! (gwyneth 20220213)
                DebugUtilities.WriteError($"Unable to open configuration file '{configFile}'! Aborting...");
                Environment.Exit(1);
                return;
            }

            DebugUtilities.WriteInfo("RESTbot startup");
            // Sessions should never be null (?) (gwyneth 20220214)
            if (Sessions == null)
            {
                // Trouble expects us later on, when adding and removing sessions...
                DebugUtilities.WriteError("Error initialising Sessions directory; it was set to null!");
            }

            /// <summary>Get the file version of LibreMetaverse.</summary>
            /// <remarks><see href="https://stackoverflow.com/a/14612480/1035977"/> (gwyneth 20220414)</remarks>
            FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(@"LibreMetaverse.dll");

            // Print the file name and version number.
            DebugUtilities.WriteInfo($"LibreMetaverse DLL version: {myFileVersionInfo.FileDescription} {myFileVersionInfo.FileVersion}");

            DebugUtilities.WriteInfo("Loading plugins");
            RegisterAllCommands(Assembly.GetExecutingAssembly());
            DebugUtilities.WriteDebug("Loading stateful plugins");
            RegisterAllStatefulPlugins(Assembly.GetExecutingAssembly());

            DebugUtilities.WriteInfo($"Listening on port {config.networking.port.ToString()}");

            // Set up the listener / router
            Listener = new RESTBot.Server.Router(IPAddress.Parse(config.networking.ip), config.networking.port);

            StillRunning = true;
            DebugUtilities.WriteInfo("Startup complete");
            uptime = DateTime.Now;

            // let's see if we can figure out how much memory is being wasted
            int stupidCounter = 0;
            while (StillRunning)
            {
                System.Threading.Thread.Sleep(1);
                //TODO: Replace above with a manualresetevent

                if (stupidCounter % 3600000 == 0)                       // stop every hour and check available memory (gwyneth 20220210)
                {
                    CollectGarbage();
                }
                stupidCounter++;
            }

            Listener.StillRunning = false;
        }
Example #28
0
        public override string Process(RestBot b, Dictionary <string, string> Parameters)
        {
            try
            {
                string type   = String.Empty;
                bool   check  = true;
                float  radius = 0.0f;

                if (Parameters.ContainsKey("type"))
                {
                    type = Parameters["type"].ToString().Replace("+", " ");
                }
                else
                {
                    check = false;
                }

                if (Parameters.ContainsKey("radius"))
                {
                    check &= float.TryParse(Parameters["radius"], out radius);
                }
                else
                {
                    check = false;
                }

                if (!check)
                {
                    return("<error>parameters have to be type, radius</error>");
                }

                // *** get current location ***
                Vector3 location = b.Client.Self.SimPosition;

                // *** find all objects in radius ***
                List <Primitive> prims = b.Client.Network.CurrentSim.ObjectsPrimitives.FindAll(
                    delegate(Primitive prim)
                {
                    Vector3 pos = prim.Position;
                    return((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius));
                }
                    );

                // *** request properties of these objects ***
                bool complete = RequestObjectProperties(prims, 0);

                String resultSet = String.Empty;

                foreach (Primitive p in prims)
                {
                    string?name = p.Properties != null ? p.Properties.Name : null;
                    if (String.IsNullOrEmpty(type) || ((name != null) && (name.Contains(type))))
                    {
                        resultSet += $"<prim><name>{name}</name><pos>{p.Position.X},{p.Position.Y},{p.Position.Z}</pos><id>{p.ID}</id></prim>";
                    }
                }
                return("<nearby_prims>" + resultSet + "</nearby_prims>");
            }
            catch (Exception e)
            {
                DebugUtilities.WriteError(e.Message);
                return($"<error>{e.Message}</error>");
            }
        }
Example #29
0
        /// <summary>
        /// Process a request (assuming it exists)
        /// </summary>
        /// <param name="headers">Request headers (including path, etc.)</param>
        /// <param name="body">Request body (will usually have all parameters from POST)</param>
        public static string DoProcessing(RequestHeaders headers, string body)
        {
            // Abort if we don't even have a valid configuration; too many things depend on it... (gwyneth 20220213)
            if (Program.config == null)
            {
                return("<error>No valid configuration loaded, aborting</error>");
            }

            //Setup variables
            DebugUtilities.WriteInfo($"New request - {headers.RequestLine.Path}");
            //Split the URL
            string[] parts = headers.RequestLine.Path.Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length < 1)
            {
                return("<error>invalidmethod</error>");
            }
            string Method = parts[0];
            /// <summary>Process the request params from POST, URL</summary>
            Dictionary <string, string> Parameters = RestBot.HandleDataFromRequest(headers, body);
            string debugparams = String.Empty;
            string debugparts  = String.Empty;

            foreach (KeyValuePair <string, string> kvp in Parameters)
            {
                debugparams = debugparams + "[" + kvp.Key + "=" + kvp.Value + "] ";
            }
            DebugUtilities.WriteDebug($"Parameters (total: {Parameters.Count()}) - '{debugparams}'");
            foreach (string s in parts)
            {
                debugparts = debugparts + "[ " + s + " ]";
            }
            DebugUtilities.WriteDebug($"Parts (total: {parts.Count()}) - '{debugparts}'");
            if (Method == "establish_session")
            {
                DebugUtilities.WriteDebug("We have an `establish_session` method.");
                // Alright, we're going to try to establish a session
                // Start location is optional (gwyneth 20220421)
                if (parts.Length >= 2 && parts[1] == Program.config.security.serverPass &&
                    Parameters.ContainsKey("first") && Parameters.ContainsKey("last") && Parameters.ContainsKey("pass"))
                {
                    DebugUtilities.WriteDebug("Found required parameters for establish_session");
                    if (Sessions != null)
                    {
                        foreach (KeyValuePair <UUID, Session> ss in Sessions)
                        {
                            if (ss.Value != null && ss.Value.Bot != null)
                            {
                                DebugUtilities.WriteSpecial($"Avatar check: [{ss.Value.Bot.First.ToLower()}/{ss.Value.Bot.Last.ToLower()}] = [{Parameters["first"].ToLower()}/{Parameters["last"].ToLower()}]");
                                if (Parameters["first"].ToLower() == ss.Value.Bot.First.ToLower() &&
                                    Parameters["last"].ToLower() == ss.Value.Bot.Last.ToLower()
                                    )
                                {
                                    DebugUtilities.WriteWarning($"Already running avatar {Parameters["first"]} {Parameters["last"]}");

                                    /// <value>Temporary string to construct a full response, if possible; if not, we catch the
                                    /// exception and return a much shorter version</value>
                                    /// <remarks>This is a hack. The issue is that we're probably acessing nullable
                                    /// elements without checking. (gwyneth 20220428)</remarks>
                                    string returnString = "";

                                    try
                                    {
                                        // Attempt to get a
                                        returnString = $@"<existing_session>true</existing_session>
	<session_id>{ss.Key.ToString()}</session_id>
	<key>{ss.Value.Bot.Client.Self.AgentID.ToString()}</key>
	<name>{ss.Value.Bot.Client.Self.FirstName} {ss.Value.Bot.Client.Self.LastName}</name>
	<FirstName>{ss.Value.Bot.Client.Self.FirstName}</FirstName>
	<LastName>{ss.Value.Bot.Client.Self.LastName}</LastName>
	<status>{ss.Value.Bot.myStatus.ToString()}</status>
	<uptime>{ss.Value.Bot.getUptimeISO8601()}</uptime>
	<start>{ss.Value.Bot.Start}</start>
	<CurrentSim>{ss.Value.Bot.Client.Network.CurrentSim.ToString()}</CurrentSim>
	<Position>{ss.Value.Bot.Client.Self.SimPosition.X},{ss.Value.Bot.Client.Self.SimPosition.Y},{ss.Value.Bot.Client.Self.SimPosition.Z}</Position>
	<Rotation>{ss.Value.Bot.Client.Self.SimRotation.X},{ss.Value.Bot.Client.Self.SimRotation.Y},{ss.Value.Bot.Client.Self.SimRotation.Z},{ss.Value.Bot.Client.Self.SimRotation.W}</Rotation>
";
                                    }
                                    catch (Exception e)
                                    {
                                        DebugUtilities.WriteError($"Could not generate full response, error was: '{e.Message}'; falling back to the simple, minimalistic answer");
                                        returnString = $"<existing_session>true</existing_session><session_id>{ss.Key.ToString()}</session_id>";
                                    }
                                    return(returnString);
                                }
                            }
                        }
                    }
                    else
                    {
                        DebugUtilities.WriteDebug("No available sessions...");
                    }
                    UUID    id = UUID.Random();
                    Session s  = new Session();
                    s.ID           = id;
                    s.Hostname     = headers.Hostname;
                    s.LastAccessed = DateTime.Now;
                    // Needs the $1$ for the md5 on the login for LibreMetaverse
                    if (!Parameters["pass"].StartsWith("$1$"))
                    {
                        Parameters["pass"] = "******" + Parameters["pass"];
                    }
                    // check if user has provided us with a starting location (default is to use the last location)
                    // (gwyneth 20220420)
                    string gridLocation = Parameters.ContainsKey("start") ? Parameters["start"] : "last";
                    s.Bot = new RestBot(s.ID, Parameters["first"], Parameters["last"], Parameters["pass"], gridLocation);

                    if (Sessions != null)
                    {
                        lock (Sessions)
                        {
                            Sessions.Add(id, s);
                        }
                    }
                    else
                    {
                        // no "else", we have no dictionary
                        DebugUtilities.WriteWarning("Possible issue: we have null Sessions when adding, which shouldn't happen");
                    }
                    RestBot.LoginReply reply = s.Bot.Login();
                    if (reply.wasFatal)
                    {
                        if (Sessions != null)
                        {
                            lock (Sessions)
                            {
                                if (Sessions.ContainsKey(id))
                                {
                                    Sessions.Remove(id);
                                }
                            }
                        }
                        else
                        {
                            // no "else", we have no dictionary
                            DebugUtilities.WriteWarning("Possible issue: we have null Sessions when removing, which shouldn't happen");
                        }
                    }
                    return(reply.xmlReply);
                }
                else
                {
                    String result = String.Empty;
                    if (parts.Length < 2)
                    {
                        result = "Missing a part.";
                    }
                    if (!Parameters.ContainsKey("first"))
                    {
                        result = result + " Missing 'first' arg.";
                    }
                    if (!Parameters.ContainsKey("last"))
                    {
                        result = result + " Missing 'last' arg.";
                    }
                    if (!Parameters.ContainsKey("pass"))
                    {
                        result = result + " Missing 'pass' arg.";
                    }
                    return($"<error>arguments: {result}</error>");
                }
            }
            // Note: formerly undocumented functionality!! (gwyneth 20220414)
            else if (Method == "server_quit")
            {
                if (parts.Length < 2)
                {
                    return($"<error>{Method}: missing 'pass' arg.</error>");
                }
                if (parts[1] == Program.config.security.serverPass)
                {
                    if (Sessions != null)
                    {
                        foreach (KeyValuePair <UUID, Session> s in Sessions)
                        {
                            lock (Sessions) DisposeSession(s.Key);
                        }
                        StillRunning = false;
                        // note: a caveat of this undocumented method is that it requires a _new_
                        // incoming request to actually kill the server... could be a ping, though. (gwyneth 20220414)
                        return("<status>success - all bot sessions were logged out and a request was made for queued shutdown</status>");
                    }
                    else
                    {
                        // it's fine if there are no sessions (gwyneth 20220414)
                        return("<status>success - no sessions were active</status>");
                    }
                }
                else
                {
                    // wrong password sent! (gwyneth 20220414)
                    return($"<error>{Method}: server authentication failure</error>");
                }
            }
            else if (Method == "ping")
            {
                if (parts.Length < 2)
                {
                    return($"<error>{Method}: missing 'pass' arg.</error>");
                }
                if (parts[1] == Program.config.security.serverPass)
                {
                    return($"<{Method}>I'm alive!</{Method}>");
                }
                else
                {
                    // wrong password sent! (gwyneth 20220414)
                    return($"<error>{Method}: server authentication failure</error>");
                }
            }
            else if (Method == "session_list")
            {
                if (parts.Length < 2)
                {
                    return("<error>missing 'pass' arg.</error>");
                }
                if (parts[1] == Program.config.security.serverPass)
                {
                    bool check = false;
                    if (Program.Sessions.Count != 0)                     // no sessions? that's fine, no need to abort
                    {
                        check = true;
                    }

                    string response = $"<{Method}>";
                    if (check)                          // optimisation: if empty, no need to run the foreach (gwyneth 20220424)
                    {
                        foreach (KeyValuePair <OpenMetaverse.UUID, RESTBot.Session> kvp in Program.Sessions)
                        {
                            if (kvp.Value.Bot != null && kvp.Value.Bot.Client != null && kvp.Value.Bot.Client.Self != null && kvp.Value.Bot.Client.Network != null)
                            {
                                response += $@"
	<session>
		<session_id>{kvp.Key.ToString()}</session_id>
		<key>{kvp.Value.Bot.Client.Self.AgentID.ToString()}</key>
		<name>{kvp.Value.Bot.Client.Self.FirstName} {kvp.Value.Bot.Client.Self.LastName}</name>
		<FirstName>{kvp.Value.Bot.Client.Self.FirstName}</FirstName>
		<LastName>{kvp.Value.Bot.Client.Self.LastName}</LastName>
		<status>{kvp.Value.Bot.myStatus.ToString()}</status>
		<uptime>{kvp.Value.Bot.getUptimeISO8601()}</uptime>
		<start>{kvp.Value.Bot.Start}</start>
		<CurrentSim>{kvp.Value.Bot.Client.Network.CurrentSim.ToString()}</CurrentSim>
		<Position>{kvp.Value.Bot.Client.Self.SimPosition.X},{kvp.Value.Bot.Client.Self.SimPosition.Y},{kvp.Value.Bot.Client.Self.SimPosition.Z}</Position>
		<Rotation>{kvp.Value.Bot.Client.Self.SimRotation.X},{kvp.Value.Bot.Client.Self.SimRotation.Y},{kvp.Value.Bot.Client.Self.SimRotation.Z},{kvp.Value.Bot.Client.Self.SimRotation.W}</Rotation>
	</session>"    ;
                            }
                            else
                            {
                                // Somehow, we have a session ID that has no bot assigned;
                                // this should never be the case, but... (gwyneth 20220426)
                                response += $"<session><session_id>{kvp.Key.ToString()}</session_id><key>{UUID.Zero.ToString()}</key></session>";
                            }
                        }
                    }
                    else
                    {
                        response += "no sessions";
                    }
                    response += $"</{Method}>";
                    return(response);
                }
                else
                {
                    // wrong password sent! (gwyneth 20220414)
                    return($"<error>{Method}: server authentication failure</error>");
                }
            }
            else if (Method == "stats")
            {
                if (parts.Length < 2)
                {
                    return($"<error>{Method}: missing 'pass' arg.</error>");
                }
                if (parts[1] == Program.config.security.serverPass)
                {
                    string response = "<stats><bots>" + ((Sessions != null) ? Sessions.Count.ToString() : "0") + "</bots>"
                                      + "<uptime>" + (DateTime.Now - uptime) + "</uptime></stats>";
                    return(response);
                }
                else
                {
                    return($"<error>{Method}: server authentication failure</error>");
                }
            }

            //Only a method? pssh.
            if (parts.Length == 1)
            {
                return("<error>no session key found</error>");
            }

            UUID sess = new UUID();

            try
            {
                sess = new UUID(parts[1]);
            }
            catch (FormatException)
            {
                return("<error>cannot parse the session key</error>");
            }
            catch (Exception e)
            {
                DebugUtilities.WriteError(e.Message);
            }

            //Session checking
            if (!ValidSession(sess, headers.Hostname))
            {
                return("<error>invalidsession</error>");
            }

            //YEY PROCESSING
            RestBot?r = null;

            if (Sessions != null)
            {
                r = Sessions[sess].Bot;
            }

            if (r == null)
            {
                return($"<error>no RestBot found for session {sess.ToString()}</error>");
            }
            //Last accessed for plugins
            if (Sessions != null)
            {
                Sessions[sess].LastAccessed = DateTime.Now;
            }
            //Pre-error checking
            if (r.myStatus != RestBot.Status.Connected) //Still logging in?
            {
                return($"<error>{r.myStatus.ToString()}</error>");
            }
            else if (!r.Client.Network.Connected) //Disconnected?
            {
                return("<error>clientdisconnected</error>");
            }
            else if (Method == "exit")
            {
                DisposeSession(sess);
                return("<disposed>true</disposed>");
            }
            else if (Method == "stats")
            {
                string response = "<bots>" + ((Sessions != null) ? Sessions.Count.ToString() : "NaN") + "</bots>";
                response += "<uptime>" + (DateTime.Now - uptime) + "</uptime>";
                return(response);
            }

            return(r.DoProcessing(Parameters, parts));
        } // end DoProcessing
Example #30
0
 public override void Initialize(RestBot bot)
 {
     session = bot.sessionid;
     DebugUtilities.WriteDebug($"{session} {MethodName} startup");
 }