using System; using System.Collections.Generic; using OpenMetaverse; using System.Text.Json; using SecondBotEvents.Services; namespace SecondBotEvents.Commands { [ClassInfo("Avatars near me and Key2Name and Name2Key lookups")] public class Avatars(EventsSecondBot setmaster) : CommandsAPI(setmaster) { [About("Adds avatars to the one time accept list for interactions")] [ReturnHints("ok")] [ReturnHintsFailure("Invaild avatar uuid")] [ReturnHintsFailure("Unknown store type")] [ReturnHintsFailure("Unable to process request store")] [ArgHints("store", "What type of request to accept", "Text", "GroupInvite", ["FriendRequest", "InventoryOffer", "GroupInvite", "Teleport"])] [ArgHints("avatar", "Who to accept the request from", "AVATAR")] [ArgHints("remove", "Should this remove the entry", "BOOL")] [CmdTypeDo()] public Object AcceptNext(string store, string avatar, string remove) { ProcessAvatar(avatar); if (avataruuid == UUID.Zero) { return Failure("Invaild avatar uuid", [store, avatar, remove]); } bool toberemoved = false; if((remove == "true") || (remove == "True")) { toberemoved = true; } if(master.DataStoreService.KnownStoreType(store) == false) { return Failure("Unknown store type", [store, avatar, remove]); } if (master.DataStoreService.AddToAcceptNext(store, avataruuid, toberemoved) == false) { return Failure("Unable to process request store", [store, avatar, remove]); } return BasicReply("ok", [store, avatar, remove]); } [About("Checks if the avatar is on the accept next list (without using the token) for the given store")] [ReturnHints("true")] [ReturnHints("false")] [ReturnHintsFailure("Invaild avatar uuid")] [ReturnHintsFailure("Unknown store type")] [ArgHints("store", "What type of request to accept", "Text", "GroupInvite", ["FriendRequest", "InventoryOffer", "GroupInvite", "Teleport"])] [ArgHints("avatar", "Who to accept the request from", "AVATAR")] [CmdTypeDo()] public Object IsOnAcceptNext(string store, string avatar) { ProcessAvatar(avatar); if (avataruuid == UUID.Zero) { return Failure("Invaild avatar uuid", [store, avatar]); } if (master.DataStoreService.KnownStoreType(store) == false) { return Failure("Unknown store type", [store, avatar]); } if(master.DataStoreService.IsInAcceptNext(store,avataruuid) == false) { return BasicReply("false", [store, avatar]); } return BasicReply("true", [store, avatar]); } [About("an improved version of near me with extra details
NearMeDetails is a object formated as follows
")] [ReturnHints("array NearMeDetails")] [ReturnHintsFailure("Error not in a sim")] [CmdTypeGet()] public object NearmeWithDetails() { if (GetClient().Network.CurrentSim == null) { return BasicReply("Error not in a sim"); } List BetterNearMe = []; Utils.LongToUInts(GetClient().Network.CurrentSim.Handle, out uint mySimX, out uint mySimY); Vector3 myLocalPos = GetClient().Self.SimPosition; List sims = []; try { lock (GetClient().Network.Simulators) { sims = [.. GetClient().Network.Simulators]; } } catch { sims = [GetClient().Network.CurrentSim]; } foreach (var sim in sims) { if (sim == null || !sim.Connected) continue; Utils.LongToUInts(sim.Handle, out uint simX, out uint simY); float offsetX = (long)simX - (long)mySimX; float offsetY = (long)simY - (long)mySimY; HashSet processedAvatars = []; List avcopy = [.. sim.ObjectsAvatars.Values]; foreach (Avatar av in avcopy) { if (av.ID == GetClient().Self.AgentID) continue; processedAvatars.Add(av.ID); Vector3 localPos = av.Position; if (av.ParentID != 0 && sim.ObjectsPrimitives.TryGetValue(av.ParentID, out Primitive parentObj)) { localPos = parentObj.Position + (av.Position * parentObj.Rotation); } float relX = offsetX + localPos.X; float relY = offsetY + localPos.Y; Vector3 relPos = new Vector3(relX, relY, localPos.Z); double dist = Math.Round(Vector3.Distance(relPos, myLocalPos), 2); if (dist > 150) continue; NearMeDetails details = new() { id = av.ID.ToString(), name = av.Name, x = (int)Math.Round(relX), y = (int)Math.Round(relY), z = (int)Math.Round(localPos.Z), range = dist }; BetterNearMe.Add(details); } foreach (var kvp in sim.AvatarPositions) { UUID avID = kvp.Key; if (avID == GetClient().Self.AgentID || processedAvatars.Contains(avID)) continue; Vector3 localPos = kvp.Value; float relX = offsetX + localPos.X; float relY = offsetY + localPos.Y; Vector3 relPos = new Vector3(relX, relY, localPos.Z); double dist = Math.Round(Vector3.Distance(relPos, myLocalPos), 2); if (dist > 150) continue; string avName = master.DataStoreService.GetAvatarName(avID); if (avName == "lookup" || string.IsNullOrEmpty(avName)) avName = "Unknown"; NearMeDetails details = new() { id = avID.ToString(), name = avName, x = (int)Math.Round(relX), y = (int)Math.Round(relY), z = (int)Math.Round(localPos.Z), range = dist }; BetterNearMe.Add(details); } } return BasicReply(JsonSerializer.Serialize(BetterNearMe, JsonOptions.UnsafeRelaxed)); } [About("Requests the given avatars profile image")] [ReturnHints("profile UUID")] [ReturnHintsFailure("Invaild avatar uuid")] [ReturnHints("Requesting avatar details [Retry later]")] [ArgHints("avatar", "Who are we getting the profile image of", "AVATAR")] [CmdTypeGet()] public object GetProfileImage(string avatar) { ProcessAvatar(avatar); if (avataruuid == UUID.Zero) { return Failure("Invaild avatar uuid", [avatar]); } KeyValuePair reply = master.DataStoreService.GetAvatarAvatarProperties(avataruuid); if(reply.Key == false) { return Failure("Requesting avatar details [Retry later]", [avatar]); } return BasicReply(reply.Value.ProfileImage.ToString()); } [About("Requests the bot updates its profile image")] [ReturnHints("ok")] [ReturnHints("Requesting avatar details [Retry later]")] [ReturnHintsFailure("Invaild texture uuid")] [ArgHints("texture", "What texture to use", "UUID")] [CmdTypeSet()] public object SetProfileImage(string texture) { if (UUID.TryParse(texture, out UUID textureUUID) == false) { return Failure("Invaild texture uuid\"", [texture]); } KeyValuePair reply = master.DataStoreService.GetAvatarAvatarProperties(GetClient().Self.AgentID); if (reply.Key == false) { return Failure("Requesting avatar details [Retry later]", [texture]); } Avatar.AvatarProperties props = reply.Value; props.ProfileImage = textureUUID; GetClient().Self.UpdateProfile(props); master.DataStoreService.UpdateAvatarProperties(GetClient().Self.AgentID, props); return BasicReply("ok"); } [About("Requests the given avatars profile about me")] [ReturnHints("profile UUID")] [ReturnHintsFailure("Invaild avatar uuid")] [ReturnHints("Requesting avatar details [Retry later]")] [ArgHints("avatar", "Who are we getting the profile about of", "AVATAR")] [CmdTypeGet()] public object GetProfileAbout(string avatar) { ProcessAvatar(avatar); if (avataruuid == UUID.Zero) { return Failure("Invaild avatar uuid", [avatar]); } KeyValuePair reply = master.DataStoreService.GetAvatarAvatarProperties(avataruuid); if (reply.Key == false) { return Failure("Requesting avatar details [Retry later]", [avatar]); } return BasicReply(reply.Value.AboutText.ToString()); } [About("Requests the given avatars profile picks")] [ReturnHints("JSON array of picks")] [ReturnHintsFailure("Invaild avatar uuid")] [ReturnHints("Requesting avatar details [Retry later]")] [ArgHints("avatar", "Who are we getting the profile picks of", "AVATAR")] [CmdTypeGet()] public object GetAvatarPicks(string avatar) { ProcessAvatar(avatar); if (avataruuid == UUID.Zero) { return Failure("Invaild avatar uuid", [avatar]); } KeyValuePair> reply = master.DataStoreService.GetAvatarPicksDetailed(avataruuid); if (reply.Key == false) { return Failure("Requesting avatar details [Retry later]", [avatar]); } return BasicReply(JsonSerializer.Serialize(reply.Value, JsonOptions.UnsafeRelaxed)); } [About("Requests the given avatars display name")] [ReturnHints("display name if set or ?")] [ReturnHintsFailure("Invaild avatar uuid")] [ReturnHints("Requesting avatar details [Retry later]")] [ArgHints("avatar", "Who are we getting the profile about of", "AVATAR")] [CmdTypeGet()] public object GetDisplayName(string avatar) { ProcessAvatar(avatar); if (avataruuid == UUID.Zero) { return Failure("Invaild avatar uuid", [avatar]); } return BasicReply(master.DataStoreService.GetDisplayName(avataruuid)); } [About("Requests the bot updates its about me")] [ReturnHints("ok")] [ReturnHints("Requesting avatar details [Retry later]")] [ReturnHintsFailure("about text to short")] [ReturnHintsFailure("about text to long")] [ArgHints("abouttext", "text to use in the about me area, length 10 to 510 bytes", "Text", "Hello world!")] [CmdTypeSet()] public object SetProfileAbout(string abouttext) { if(abouttext.Length < 10) { return Failure("About text to short", [abouttext]); } else if (System.Text.Encoding.UTF8.GetByteCount(abouttext) > 510) { return Failure("About text to long", [abouttext]); } KeyValuePair reply = master.DataStoreService.GetAvatarAvatarProperties(GetClient().Self.AgentID); if (reply.Key == false) { return Failure("Requesting avatar details [Retry later]", [abouttext]); } Avatar.AvatarProperties props = reply.Value; props.AboutText = abouttext; GetClient().Self.UpdateProfile(props); master.DataStoreService.UpdateAvatarProperties(GetClient().Self.AgentID, props); return BasicReply("ok"); } [About("returns a list of all known avatars nearby")] [ReturnHints("array UUID = Name")] [ReturnHintsFailure("Error not in a sim")] [CmdTypeGet()] public object Nearme() { if (GetClient().Network.CurrentSim == null) { return BasicReply("Error not in a sim"); } Dictionary NearMe = []; List avcopy = [.. GetClient().Network.CurrentSim.ObjectsAvatars.Values]; foreach (Avatar av in avcopy) { if (av.ID != GetClient().Self.AgentID) { NearMe.Add(av.ID, av.Name); } } return BasicReply(JsonSerializer.Serialize(NearMe, JsonOptions.UnsafeRelaxed)); } [About("searchs the AV database if not found triggers a lookup")] [ArgHints("uuid", "What uuid are we getting the name for", "UUID")] [ReturnHints("the name of the avatar")] [ReturnHints("lookup")] [ReturnHintsFailure("Not a vaild UUID")] [CmdTypeDo()] public object Key2Name(string uuid) { if (UUID.TryParse(uuid, out UUID parsedUUID) == false) { return Failure("Not a vaild UUID"); } return BasicReply(master.DataStoreService.GetAvatarName(parsedUUID)); } [About("searchs the AV database if not found triggers a lookup")] [ReturnHints("the uuid of the avatar")] [ReturnHints("lookup")] [ReturnHintsFailure("Not a vaild name")] [ArgHints("name", "the name to find the uuid for", "Text", "Madpeter Zond")] [CmdTypeDo()] public object Name2Key(string name) { if(name == null) { return Failure("Not a vaild name"); } return BasicReply(master.DataStoreService.GetAvatarUUID(name)); } [About("Sets the bot display name")] [CmdTypeSet()] public object SetDisplayName(string newname) { if (string.IsNullOrWhiteSpace(newname)) { return Failure("Display name cannot be empty"); } GetClient().Self.SetDisplayName(GetClient().Self.Name, newname); return BasicReply("ok"); } [About("Sets the bot first life profile text and image")] [CmdTypeSet()] public object SetFirstLife(string text, string image) { if (UUID.TryParse(image, out UUID imageUUID) == false) { return Failure("Invalid image uuid"); } KeyValuePair reply = master.DataStoreService.GetAvatarAvatarProperties(GetClient().Self.AgentID); if (reply.Key == false) { return Failure("Requesting avatar details [Retry later]"); } Avatar.AvatarProperties props = reply.Value; props.FirstLifeText = text; props.FirstLifeImage = imageUUID; GetClient().Self.UpdateProfile(props); master.DataStoreService.UpdateAvatarProperties(GetClient().Self.AgentID, props); return BasicReply("ok"); } [About("Creates or updates a profile pick")] [CmdTypeSet()] public object SetAvatarPick(string id, string name, string desc, string snapshot, string sim, string pos) { if (UUID.TryParse(id, out UUID pickUUID) == false) { return Failure("Invalid pick uuid"); } if (UUID.TryParse(snapshot, out UUID snapshotUUID) == false) { snapshotUUID = UUID.Zero; } Vector3 position = Vector3.Zero; if (Vector3.TryParse(pos, out Vector3 parsedPos)) { position = parsedPos; } Vector3d globalPos = GetClient().Self.GlobalPosition; if (!string.IsNullOrWhiteSpace(sim) && sim == GetClient().Network.CurrentSim.Name) { Utils.LongToUInts(GetClient().Network.CurrentSim.Handle, out uint x, out uint y); globalPos = new Vector3d(x + position.X, y + position.Y, position.Z); } GetClient().Self.PickInfoUpdate(pickUUID, false, UUID.Zero, name, globalPos, snapshotUUID, desc); master.DataStoreService.ClearAvatarPicksCache(GetClient().Self.AgentID); return BasicReply("ok"); } [About("Deletes a profile pick")] [CmdTypeSet()] public object DeleteAvatarPick(string id) { if (UUID.TryParse(id, out UUID pickUUID) == false) { return Failure("Invalid pick uuid"); } GetClient().Self.PickDelete(pickUUID); master.DataStoreService.ClearAvatarPicksCache(GetClient().Self.AgentID); return BasicReply("ok"); } [About("Creates or updates a classified ad")] [CmdTypeSet()] public object SetAvatarClassified(string id, string name, string desc, string snapshot, string category, string price, string autorenew) { if (UUID.TryParse(id, out UUID classifiedUUID) == false) { return Failure("Invalid classified uuid"); } if (UUID.TryParse(snapshot, out UUID snapshotUUID) == false) { snapshotUUID = UUID.Zero; } int adPrice = 50; int.TryParse(price, out adPrice); bool renew = autorenew.ToLower() == "true"; DirectoryManager.ClassifiedCategories cat = DirectoryManager.ClassifiedCategories.Shopping; if (Enum.TryParse(category, out DirectoryManager.ClassifiedCategories parsedCat)) { cat = parsedCat; } GetClient().Self.UpdateClassifiedInfo(classifiedUUID, cat, snapshotUUID, adPrice, name, desc, renew); master.DataStoreService.ClearAvatarClassifiedsCache(GetClient().Self.AgentID); return BasicReply("ok"); } [About("Deletes a classified ad")] [CmdTypeSet()] public object DeleteAvatarClassified(string id) { if (UUID.TryParse(id, out UUID classifiedUUID) == false) { return Failure("Invalid classified uuid"); } GetClient().Self.DeleteClassified(classifiedUUID); master.DataStoreService.ClearAvatarClassifiedsCache(GetClient().Self.AgentID); return BasicReply("ok"); } [About("Requests the given avatars profile classifieds")] [CmdTypeGet()] public object GetAvatarClassifieds(string avatar) { ProcessAvatar(avatar); if (avataruuid == UUID.Zero) { return Failure("Invaild avatar uuid", [avatar]); } KeyValuePair> reply = master.DataStoreService.GetAvatarClassifiedsDetailed(avataruuid); if (reply.Key == false) { return Failure("Requesting avatar details [Retry later]", [avatar]); } return BasicReply(JsonSerializer.Serialize(reply.Value, JsonOptions.UnsafeRelaxed)); } [About("Requests the given avatars first life profile text")] [CmdTypeGet()] public object GetFirstLifeText(string avatar) { ProcessAvatar(avatar); if (avataruuid == UUID.Zero) { return Failure("Invaild avatar uuid", [avatar]); } KeyValuePair reply = master.DataStoreService.GetAvatarAvatarProperties(avataruuid); if (reply.Key == false) { return Failure("Requesting avatar details [Retry later]", [avatar]); } return BasicReply(reply.Value.FirstLifeText.ToString()); } [About("Requests the given avatars first life profile image")] [CmdTypeGet()] public object GetFirstLifeImage(string avatar) { ProcessAvatar(avatar); if (avataruuid == UUID.Zero) { return Failure("Invaild avatar uuid", [avatar]); } KeyValuePair reply = master.DataStoreService.GetAvatarAvatarProperties(avataruuid); if (reply.Key == false) { return Failure("Requesting avatar details [Retry later]", [avatar]); } return BasicReply(reply.Value.FirstLifeImage.ToString()); } [About("Requests the given avatars profile groups")] [CmdTypeGet()] public object GetAvatarGroups(string avatar) { ProcessAvatar(avatar); if (avataruuid == UUID.Zero) { return Failure("Invaild avatar uuid", [avatar]); } KeyValuePair> reply = master.DataStoreService.GetAvatarGroups(avataruuid); if (reply.Key == false) { return Failure("Requesting avatar details [Retry later]", [avatar]); } return BasicReply(JsonSerializer.Serialize(reply.Value, JsonOptions.UnsafeRelaxed)); } } }