From 92bc9dceb97c5b63a9ba8d496e9ffd53ed4f5633 Mon Sep 17 00:00:00 2001 From: Madpeterz <57852827+Madpeterz@users.noreply.github.com> Date: Sun, 7 Feb 2021 19:03:33 +0000 Subject: [PATCH] group role storage and more adds new http namespace parcelestate adds grouprole metadata storage adds the following http commands: parcelestate/parcelbanlist groups/ismember groups/listgrouproles Adds new core command getparcelbanlist --- BSBshared/BotTypes/BasicBot.cs | 2 + CLI/HttpService/Group.cs | 103 +++++++++++++++++++- CLI/HttpService/HttpAsService.cs | 7 +- CLI/HttpService/ParcelEstate.cs | 50 ++++++++++ CLI/WikiMake/wikimake.cs | 1 + Core/Commands/Parcel/GetParcelBanlist.cs | 27 +++++ Core/Commands/Parcel/GetParcelFlags.cs | 2 +- Core/Commands/Parcel/ParcelReturnObjects.cs | 2 +- Core/Commands/Parcel/SetParcelFlag.cs | 2 +- Core/bottypes/AwaitReplyEventBot.cs | 21 +++- 10 files changed, 209 insertions(+), 8 deletions(-) create mode 100644 CLI/HttpService/ParcelEstate.cs create mode 100644 Core/Commands/Parcel/GetParcelBanlist.cs diff --git a/BSBshared/BotTypes/BasicBot.cs b/BSBshared/BotTypes/BasicBot.cs index 8fd91d0..15ce175 100644 --- a/BSBshared/BotTypes/BasicBot.cs +++ b/BSBshared/BotTypes/BasicBot.cs @@ -133,8 +133,10 @@ namespace BetterSecondBotShared.bottypes } protected Dictionary mygroups = new Dictionary(); + protected Dictionary>> mygrouprolesstorage = new Dictionary>>(); public Dictionary MyGroups { get { return mygroups; } } + public Dictionary>> MyGroupRolesStorage { get { return mygrouprolesstorage; } } protected GridClient Client; public GridClient GetClient { get { return Client; } } diff --git a/CLI/HttpService/Group.cs b/CLI/HttpService/Group.cs index c16da48..ebb53e3 100644 --- a/CLI/HttpService/Group.cs +++ b/CLI/HttpService/Group.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Text; using OpenMetaverse; using Newtonsoft.Json; +using BetterSecondBotShared.Static; namespace BetterSecondBot.HttpService { @@ -15,6 +16,47 @@ namespace BetterSecondBot.HttpService { public HttpApiGroup(SecondBot mainbot, TokenStorage setuptokens) : base(mainbot, setuptokens) { } + + [About("Checks if the given UUID is in the given group
Note: if group membership data is more than 60 secs old this will return Updating
Please wait and retry later")] + [ReturnHints("True|False")] + [ReturnHints("Updating")] + [ReturnHints("Unknown group")] + [ReturnHints("Invaild group UUID")] + [ReturnHints("Unable to find avatar UUID")] + [Route(HttpVerbs.Get, "/ismember/{group}/{avatar}/{token}")] + public object ismember(string group,string avatar,string token) + { + if (tokens.Allow(token, getClientIP()) == true) + { + if (UUID.TryParse(group, out UUID groupuuid) == true) + { + if (bot.MyGroups.ContainsKey(groupuuid) == true) + { + if (bot.NeedReloadGroupData(groupuuid) == false) + { + UUID avataruuid = UUID.Zero; + if(UUID.TryParse(avatar,out avataruuid) == false) + { + string lookup = bot.FindAvatarName2Key(avatar); + if (UUID.TryParse(lookup, out avataruuid) == false) + { + return BasicReply("Unable to find avatar UUID"); + } + } + bool status = bot.FastCheckInGroup(groupuuid, avataruuid); + return BasicReply(status.ToString()); + } + bot.GetClient.Groups.RequestGroupMembers(groupuuid); + return BasicReply("Updating"); + } + return BasicReply("Unknown group"); + } + return BasicReply("Invaild group UUID"); + } + return BasicReply("Token not accepted"); + } + + [About("fetchs a list of all groups known to the bot")] [ReturnHints("array UUID=name")] [Route(HttpVerbs.Get, "/listgroups/{token}")] @@ -32,10 +74,62 @@ namespace BetterSecondBot.HttpService return BasicReply("Token not accepted"); } + [About("Requests the roles for the selected group
Replys with GroupRoleDetails object formated as follows
  • UpdateUnderway (Bool)
  • RoleDataAge (Int) [default -1]
  • Roles (KeyPair array of UUID=Name)

")] + [ArgHints("group", "URLARG", "UUID of the group")] + [ReturnHints("GroupRoleDetails object")] + [ReturnHints("Group is not currently known")] + [ReturnHints("Invaild group UUID")] + [ReturnHints("Updating")] + [Route(HttpVerbs.Get, "/listgrouproles/{group}/{token}")] + public object listgrouproles(string group, string token) + { + if (tokens.Allow(token, getClientIP()) == true) + { + if (UUID.TryParse(group, out UUID groupuuid) == true) + { + if (bot.MyGroups.ContainsKey(groupuuid) == true) + { + GroupRoleDetails reply = new GroupRoleDetails(); + reply.UpdateUnderway = false; + reply.RoleDataAge = -1; + reply.Roles = new Dictionary(); + if (bot.MyGroupRolesStorage.ContainsKey(groupuuid) == false) + { + reply.UpdateUnderway = true; + } + else + { + long dif = helpers.UnixTimeNow() - bot.MyGroupRolesStorage[groupuuid].Key; + if(dif >= 120) + { + reply.UpdateUnderway = true; + reply.RoleDataAge = dif; + } + foreach(GroupRole gr in bot.MyGroupRolesStorage[groupuuid].Value) + { + reply.Roles.Add(gr.ID.ToString(), gr.Name); + } + } + if(reply.UpdateUnderway == true) + { + if(reply.Roles.Count == 0) + { + return BasicReply("Updating"); + } + } + return BasicReply(JsonConvert.SerializeObject(reply)); + } + return BasicReply("Group is not currently known"); + } + return BasicReply("Invaild group UUID"); + } + return BasicReply("Token not accepted"); + } + [About("fetchs a list of all groups with unread messages")] [ReturnHints("array UUID")] [Route(HttpVerbs.Get, "/listgroupswithunread/{token}")] - public object listgroupswithunread(string group, string token) + public object listgroupswithunread(string token) { if (tokens.Allow(token, getClientIP()) == true) { @@ -93,7 +187,12 @@ namespace BetterSecondBot.HttpService } return BasicReply("Token not accepted"); } + } - + public class GroupRoleDetails + { + public bool UpdateUnderway { get; set; } + public Dictionary Roles { get; set; } + public long RoleDataAge = 0; } } diff --git a/CLI/HttpService/HttpAsService.cs b/CLI/HttpService/HttpAsService.cs index 715dc1c..4788d00 100644 --- a/CLI/HttpService/HttpAsService.cs +++ b/CLI/HttpService/HttpAsService.cs @@ -61,8 +61,11 @@ namespace BetterSecondBot.HttpService .WithController(() => new HttpApiIM(Bot, Tokens)) ) .WithWebApi("/core", m => m - .WithController(() => new HttpApiCore(Config, Bot, Tokens))) - + .WithController(() => new HttpApiCore(Config, Bot, Tokens)) + ) + .WithWebApi("/parcelestate", m => m + .WithController(() => new HttpApiParcelEstate(Bot,Tokens)) + ) .WithModule(new ActionModule("/", HttpVerbs.Any, ctx => ctx.SendDataAsync(new { Message = "Error" }))); return server; } diff --git a/CLI/HttpService/ParcelEstate.cs b/CLI/HttpService/ParcelEstate.cs new file mode 100644 index 0000000..ac442b8 --- /dev/null +++ b/CLI/HttpService/ParcelEstate.cs @@ -0,0 +1,50 @@ +using BSB.bottypes; +using BSB.Static; +using EmbedIO; +using EmbedIO.Routing; +using EmbedIO.WebApi; +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; +using Newtonsoft.Json; +using static OpenMetaverse.ParcelManager; + +namespace BetterSecondBot.HttpService +{ + class HttpApiParcelEstate: WebApiControllerWithTokens + { + public HttpApiParcelEstate(SecondBot mainbot, TokenStorage setuptokens) : base(mainbot, setuptokens) { } + + [About("Fetchs the parcel ban list of the parcel the bot is currently on
If the name returned is lookup the bot is currently requesting the avatar name")] + [ReturnHints("array of UUID=Name")] + [ReturnHints("Error not in a sim")] + [ReturnHints("Parcel data not ready")] + [Route(HttpVerbs.Get, "/parcelbanlist/{token}")] + public object parcelbanlist(string token) + { + if (tokens.Allow(token, getClientIP()) == true) + { + if (bot.GetClient.Network.CurrentSim != null) + { + int localid = bot.GetClient.Parcels.GetParcelLocalID(bot.GetClient.Network.CurrentSim, bot.GetClient.Self.SimPosition); + Parcel targetparcel = null; + if (bot.GetClient.Network.CurrentSim.Parcels.ContainsKey(localid) == true) + { + targetparcel = bot.GetClient.Network.CurrentSim.Parcels[localid]; + Dictionary reply = new Dictionary(); + foreach (ParcelAccessEntry e in targetparcel.AccessBlackList) + { + string name = bot.FindAvatarKey2Name(e.AgentID); + reply.Add(e.AgentID.ToString(), name); + } + return BasicReply(JsonConvert.SerializeObject(reply)); + } + return BasicReply("Parcel data not ready"); + } + return BasicReply("Error not in a sim"); + } + return BasicReply("Token not accepted"); + } + } +} diff --git a/CLI/WikiMake/wikimake.cs b/CLI/WikiMake/wikimake.cs index aa7e904..b2844ac 100644 --- a/CLI/WikiMake/wikimake.cs +++ b/CLI/WikiMake/wikimake.cs @@ -566,6 +566,7 @@ namespace BetterSecondBot.WikiMake createEndpoint("im", typeof(HttpApiIM)); createEndpoint("groups", typeof(HttpApiGroup)); createEndpoint("chat", typeof(HttpApiLocalchat)); + createEndpoint("parcelestate", typeof(HttpApiParcelEstate)); } public string getCommandMethod(string endpoint, string command) diff --git a/Core/Commands/Parcel/GetParcelBanlist.cs b/Core/Commands/Parcel/GetParcelBanlist.cs new file mode 100644 index 0000000..55764de --- /dev/null +++ b/Core/Commands/Parcel/GetParcelBanlist.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; +using static OpenMetaverse.ParcelManager; + +namespace BSB.Commands.Parcel +{ + class GetParcelBanlist : ParcelCommand_CheckParcel_1arg_smart + { + public override string Helpfile { get { return "Fetchs the current parcels banlist and sends it to the smart reply target on [ARG 1]"; } } + + public override bool CallFunction(string[] args) + { + if (base.CallFunction(args) == true) + { + Dictionary reply = new Dictionary(); + foreach(ParcelAccessEntry e in targetparcel.AccessBlackList) + { + string name = bot.FindAvatarKey2Name(e.AgentID); + reply.Add(e.AgentID.ToString(), name); + } + return bot.GetCommandsInterface.SmartCommandReply(true, args[0], targetparcel.Name, CommandName, reply); + } + return false; + } + } +} diff --git a/Core/Commands/Parcel/GetParcelFlags.cs b/Core/Commands/Parcel/GetParcelFlags.cs index d97bd2b..9a16843 100644 --- a/Core/Commands/Parcel/GetParcelFlags.cs +++ b/Core/Commands/Parcel/GetParcelFlags.cs @@ -55,7 +55,7 @@ namespace BSB.Commands.CMD_Parcel int localid = bot.GetClient.Parcels.GetParcelLocalID(bot.GetClient.Network.CurrentSim, bot.GetClient.Self.SimPosition); if (bot.GetClient.Network.CurrentSim.Parcels.ContainsKey(localid) == true) { - Parcel p = bot.GetClient.Network.CurrentSim.Parcels[localid]; + OpenMetaverse.Parcel p = bot.GetClient.Network.CurrentSim.Parcels[localid]; Dictionary collection = new Dictionary(); foreach (string cfg in get_flags) { diff --git a/Core/Commands/Parcel/ParcelReturnObjects.cs b/Core/Commands/Parcel/ParcelReturnObjects.cs index 120549a..41adc94 100644 --- a/Core/Commands/Parcel/ParcelReturnObjects.cs +++ b/Core/Commands/Parcel/ParcelReturnObjects.cs @@ -19,7 +19,7 @@ namespace BSB.Commands.CMD_Parcel if (owner_uuids.Count > 0) { int localid = bot.GetClient.Parcels.GetParcelLocalID(bot.GetClient.Network.CurrentSim, bot.GetClient.Self.SimPosition); - Parcel p = bot.GetClient.Network.CurrentSim.Parcels[localid]; + OpenMetaverse.Parcel p = bot.GetClient.Network.CurrentSim.Parcels[localid]; if (bot.GetClient.Network.CurrentSim.Parcels.ContainsKey(localid) == true) { if (parcel_static.has_parcel_perm(p, bot) == true) diff --git a/Core/Commands/Parcel/SetParcelFlag.cs b/Core/Commands/Parcel/SetParcelFlag.cs index 04b0340..a69488b 100644 --- a/Core/Commands/Parcel/SetParcelFlag.cs +++ b/Core/Commands/Parcel/SetParcelFlag.cs @@ -55,7 +55,7 @@ namespace BSB.Commands.CMD_Parcel int localid = bot.GetClient.Parcels.GetParcelLocalID(bot.GetClient.Network.CurrentSim, bot.GetClient.Self.SimPosition); if (bot.GetClient.Network.CurrentSim.Parcels.ContainsKey(localid) == true) { - Parcel p = bot.GetClient.Network.CurrentSim.Parcels[localid]; + OpenMetaverse.Parcel p = bot.GetClient.Network.CurrentSim.Parcels[localid]; if (parcel_static.has_parcel_perm(p, bot) == true) { foreach (KeyValuePair cfg in setflags) diff --git a/Core/bottypes/AwaitReplyEventBot.cs b/Core/bottypes/AwaitReplyEventBot.cs index e22a4f1..7727254 100644 --- a/Core/bottypes/AwaitReplyEventBot.cs +++ b/Core/bottypes/AwaitReplyEventBot.cs @@ -3,7 +3,8 @@ using System; using System.Collections.Generic; using System.Text; using OpenMetaverse; - +using BetterSecondBotShared.Static; + namespace BSB.bottypes { public abstract class AwaitReplyEventBot : CommandsBot @@ -111,6 +112,24 @@ namespace BSB.bottypes { if(await_events.ContainsKey("grouproles") == true) { + // update group role storage + List entrys = new List(); + foreach(GroupRole gr in e.Roles.Values) + { + entrys.Add(gr); + } + + KeyValuePair> storage = new KeyValuePair>(helpers.UnixTimeNow(), entrys); + if (mygrouprolesstorage.ContainsKey(e.GroupID) == false) + { + mygrouprolesstorage.Add(e.GroupID, storage); + } + else + { + mygrouprolesstorage[e.GroupID] = storage; + } + + List PurgeAwaiters = new List(); foreach(KeyValuePair> await_reply in await_events["grouproles"]) {