token mania!
This commit is contained in:
parent
4558b695f5
commit
50ff8f0c5f
33 changed files with 5363 additions and 408 deletions
|
|
@ -201,60 +201,6 @@ namespace BetterSecondBot.HttpService
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
|
||||||
public class About : Attribute
|
|
||||||
{
|
|
||||||
public string about = "";
|
|
||||||
public About(string about)
|
|
||||||
{
|
|
||||||
this.about = about;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
|
||||||
public class NeedsToken : Attribute
|
|
||||||
{
|
|
||||||
public bool needsToken = true;
|
|
||||||
public NeedsToken(bool needsToken)
|
|
||||||
{
|
|
||||||
this.needsToken = needsToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
|
|
||||||
public class ReturnHints : Attribute
|
|
||||||
{
|
|
||||||
public string hint = "";
|
|
||||||
public bool good = true;
|
|
||||||
public ReturnHints(string hint)
|
|
||||||
{
|
|
||||||
this.hint = hint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
|
|
||||||
public class ReturnHintsFailure : ReturnHints
|
|
||||||
{
|
|
||||||
public ReturnHintsFailure(string hint): base(hint)
|
|
||||||
{
|
|
||||||
this.good = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
|
|
||||||
public class ArgHints : Attribute
|
|
||||||
{
|
|
||||||
public string name = "";
|
|
||||||
public string typename = "";
|
|
||||||
public string about = "";
|
|
||||||
|
|
||||||
public ArgHints(string name,string typename, string about)
|
|
||||||
{
|
|
||||||
this.name = name;
|
|
||||||
this.typename = typename;
|
|
||||||
this.about = about;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
69
SecondBotEvents/Commands/Animation.cs
Normal file
69
SecondBotEvents/Commands/Animation.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
internal class Animation : CommandsAPI
|
||||||
|
{
|
||||||
|
public Animation(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Toggles if animation requests from this avatar (used for remote poseballs) are accepted")]
|
||||||
|
[ReturnHints("Granted perm animation")]
|
||||||
|
[ReturnHints("Removed perm animation")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[ArgHints("avatar", "URLARG", "UUID (or Firstname Lastname)")]
|
||||||
|
[Route(HttpVerbs.Get, "/AddToAllowAnimations/{avatar}/{token}")]
|
||||||
|
public object AddToAllowAnimations(string avatar, string token)
|
||||||
|
{
|
||||||
|
if(AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return BasicReply("avatar lookup", "AddToAllowAnimations", new [] { avatar });
|
||||||
|
}
|
||||||
|
// @todo accept storage
|
||||||
|
return Failure("@todo", "AddToAllowAnimations");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Attempts to play a gesture")]
|
||||||
|
[ReturnHintsFailure("Error with gesture")]
|
||||||
|
[ReturnHints("Accepted")]
|
||||||
|
[ArgHints("gesture", "URLARG", "Inventory UUID of the gesture")]
|
||||||
|
[Route(HttpVerbs.Get, "/PlayGesture/{gesture}/{token}")]
|
||||||
|
public object PlayGesture(string gesture, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(gesture, out UUID gestureUUID) == false)
|
||||||
|
{
|
||||||
|
return BasicReply("Error with gesture", "PlayGesture", new [] { gesture });
|
||||||
|
}
|
||||||
|
InventoryItem itm = getClient().Inventory.FetchItem(gestureUUID, getClient().Self.AgentID, (3 * 1000));
|
||||||
|
getClient().Self.PlayGesture(itm.AssetUUID);
|
||||||
|
return BasicReply("Accepted", "PlayGesture", new [] { gesture });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Resets the animation stack for the bot")]
|
||||||
|
[ReturnHints("Accepted")]
|
||||||
|
[Route(HttpVerbs.Get, "/ResetAnimations/{token}")]
|
||||||
|
public object ResetAnimations(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
// @todo Reset animations function from old version
|
||||||
|
return Failure("@todo", "ResetAnimations");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
76
SecondBotEvents/Commands/Avatars.cs
Normal file
76
SecondBotEvents/Commands/Avatars.cs
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Avatars : CommandsAPI
|
||||||
|
{
|
||||||
|
public Avatars(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("an improved version of near me with extra details<br/>NearMeDetails is a object formated as follows<br/><ul><li>id</li><li>name</li><li>x</li><li>y</li><li>z</li><li>range</li></ul>")]
|
||||||
|
[ReturnHints("array NearMeDetails")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[Route(HttpVerbs.Get, "/NearmeWithDetails/{token}")]
|
||||||
|
public object NearmeWithDetails(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (getClient().Network.CurrentSim == null)
|
||||||
|
{
|
||||||
|
return BasicReply("Error not in a sim", "nearmewithdetails");
|
||||||
|
}
|
||||||
|
List<NearMeDetails> BetterNearMe = new List<NearMeDetails>();
|
||||||
|
Dictionary<uint, Avatar> avcopy = getClient().Network.CurrentSim.ObjectsAvatars.Copy();
|
||||||
|
foreach (Avatar av in avcopy.Values)
|
||||||
|
{
|
||||||
|
if (av.ID != getClient().Self.AgentID)
|
||||||
|
{
|
||||||
|
NearMeDetails details = new NearMeDetails();
|
||||||
|
details.id = av.ID.ToString();
|
||||||
|
details.name = av.Name;
|
||||||
|
details.x = (int)Math.Round(av.Position.X);
|
||||||
|
details.y = (int)Math.Round(av.Position.Y);
|
||||||
|
details.z = (int)Math.Round(av.Position.Z);
|
||||||
|
details.range = (int)Math.Round(Vector3.Distance(av.Position, getClient().Self.SimPosition));
|
||||||
|
BetterNearMe.Add(details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(BetterNearMe), "nearmewithdetails");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("returns a list of all known avatars nearby")]
|
||||||
|
[ReturnHints("array UUID = Name")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[Route(HttpVerbs.Get, "/Nearme/{token}")]
|
||||||
|
public object Nearme(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (getClient().Network.CurrentSim == null)
|
||||||
|
{
|
||||||
|
return BasicReply("Error not in a sim", "nearme");
|
||||||
|
}
|
||||||
|
Dictionary<UUID, string> NearMe = new Dictionary<UUID, string>();
|
||||||
|
Dictionary<uint, Avatar> avcopy = getClient().Network.CurrentSim.ObjectsAvatars.Copy();
|
||||||
|
foreach (Avatar av in avcopy.Values)
|
||||||
|
{
|
||||||
|
if (av.ID != getClient().Self.AgentID)
|
||||||
|
{
|
||||||
|
NearMe.Add(av.ID, av.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(NearMe), "nearme");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
161
SecondBotEvents/Commands/Chat.cs
Normal file
161
SecondBotEvents/Commands/Chat.cs
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Chat : CommandsAPI
|
||||||
|
{
|
||||||
|
public Chat(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
[About("fetchs the last 20 localchat messages")]
|
||||||
|
[ReturnHints("array string")]
|
||||||
|
[Route(HttpVerbs.Get, "/LocalChatHistory/{token}")]
|
||||||
|
public object LocalChatHistory(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(bot.getLocalChatHistory()), "LocalChatHistory");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("sends a message to localchat")]
|
||||||
|
[ArgHints("channel", "URLARG", "the channel to output on (>=0)")]
|
||||||
|
[ArgHints("message", "Text", "the message to send")]
|
||||||
|
[ReturnHints("array string")]
|
||||||
|
[ReturnHintsFailure("Message empty")]
|
||||||
|
[ReturnHintsFailure("Invaild channel")]
|
||||||
|
[Route(HttpVerbs.Post, "/Say/{channel}/{token}")]
|
||||||
|
public object Say(string channel,[FormField] string message,string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.isempty(message) == true)
|
||||||
|
{
|
||||||
|
return Failure("Message empty", "Say", new [] { channel, message });
|
||||||
|
}
|
||||||
|
if(int.TryParse(channel,out int channelnum) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild channel", "Say", new [] { channel, message });
|
||||||
|
}
|
||||||
|
if(channelnum < 0)
|
||||||
|
{
|
||||||
|
return Failure("Invaild channel", "Say", new [] { channel, message });
|
||||||
|
}
|
||||||
|
getClient().Self.Chat(message, channelnum, ChatType.Normal);
|
||||||
|
if (channelnum == 0)
|
||||||
|
{
|
||||||
|
bot.AddToLocalChat(getClient().Self.Name, message);
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(bot.getLocalChatHistory()), "Say", new [] { channel, message });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("sends a im to the selected avatar")]
|
||||||
|
[ArgHints("avatar", "URLARG", "a UUID or Firstname Lastname")]
|
||||||
|
[ArgHints("message", "Text", "the message to send")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Message empty")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[Route(HttpVerbs.Post, "/IM/{avatar}/{token}")]
|
||||||
|
public object IM(string avatar, [FormField] string message, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if(avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("avatar lookup", "IM", new [] { avatar, message });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.isempty(message) == true)
|
||||||
|
{
|
||||||
|
return Failure("Message empty", "IM", new [] { avatar, message });
|
||||||
|
}
|
||||||
|
bot.SendIM(avataruuid, message);
|
||||||
|
return BasicReply("ok", "IM", new [] { avatar, message });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("gets a full list of all chat windows")]
|
||||||
|
[ReturnHints("array UUID = Name")]
|
||||||
|
[Route(HttpVerbs.Get, "/chatwindows/{token}")]
|
||||||
|
public object chatwindows(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(bot.GetIMChatWindowKeyNames()), "chatwindows");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("gets a list of chat windows with unread messages")]
|
||||||
|
[ReturnHints("array of UUID")]
|
||||||
|
[Route(HttpVerbs.Get, "/listwithunread/{token}")]
|
||||||
|
public object listwithunread(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
List<UUID> unreadimwindows = new List<UUID>();
|
||||||
|
foreach (UUID window in bot.IMChatWindows())
|
||||||
|
{
|
||||||
|
if (bot.ImChatWindowHasUnread(window) == true)
|
||||||
|
{
|
||||||
|
unreadimwindows.Add(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(unreadimwindows), "listwithunread");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("gets if there are any unread im messages at all")]
|
||||||
|
[ReturnHints("True|False")]
|
||||||
|
[Route(HttpVerbs.Get, "/haveunreadims/{token}")]
|
||||||
|
public object haveunreadims(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
bool reply = false;
|
||||||
|
foreach (UUID window in bot.IMChatWindows())
|
||||||
|
{
|
||||||
|
if (bot.ImChatWindowHasUnread(window) == true)
|
||||||
|
{
|
||||||
|
reply = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BasicReply(reply.ToString(), "haveunreadims");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("gets the chat from the selected window")]
|
||||||
|
[ArgHints("window", "URLARG", "the UUID of the chat window")]
|
||||||
|
[ReturnHintsFailure("Window UUID invaild")]
|
||||||
|
[ReturnHints("Array of text")]
|
||||||
|
[Route(HttpVerbs.Get, "/getimchat/{window}/{token}")]
|
||||||
|
public object getimchat(string window, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(window, out UUID windowUUID) == false)
|
||||||
|
{
|
||||||
|
return Failure("Window UUID invaild", "getimchat", new[] { window });
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(bot.GetIMChatWindow(windowUUID)), "getimchat", new[] { window });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
76
SecondBotEvents/Commands/Core.cs
Normal file
76
SecondBotEvents/Commands/Core.cs
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Core : CommandsAPI
|
||||||
|
{
|
||||||
|
public Core(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
[About("Used to check HTTP connections")]
|
||||||
|
[ReturnHints("world")]
|
||||||
|
[NeedsToken(false)]
|
||||||
|
[Route(HttpVerbs.Get, "/Hello")]
|
||||||
|
public object Hello()
|
||||||
|
{
|
||||||
|
return BasicReply("world", "Hello");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Delays a thead by X ms<br/>Mostly pointless but good if your doing custom commands")]
|
||||||
|
[ReturnHintsFailure("Invaild amount")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[Route(HttpVerbs.Get, "/Delay/{amount}/{token}")]
|
||||||
|
public object Delay(string amount,string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (int.TryParse(amount,out int amountvalue) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild amount", "Delay", new [] { amount });
|
||||||
|
}
|
||||||
|
Thread.Sleep(amountvalue);
|
||||||
|
return BasicReply("Ok", "Delay", new [] { amount });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Removes the given token from the accepted token pool")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[Route(HttpVerbs.Get, "/LogoutUI/{token}")]
|
||||||
|
public object LogoutUI(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
SuccessNoReturn("LogoutUI");
|
||||||
|
// @todo remove token from stoage
|
||||||
|
return BasicReply("ok");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommandLibCall
|
||||||
|
{
|
||||||
|
public string Command { get; set; }
|
||||||
|
public string[] Args { get; set; }
|
||||||
|
public string AuthCode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NearMeDetails
|
||||||
|
{
|
||||||
|
public string id { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public int x { get; set; }
|
||||||
|
public int y { get; set; }
|
||||||
|
public int z { get; set; }
|
||||||
|
public int range { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
95
SecondBotEvents/Commands/Dialogs.cs
Normal file
95
SecondBotEvents/Commands/Dialogs.cs
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Dialogs : CommandsAPI
|
||||||
|
{
|
||||||
|
public Dialogs(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
[About("Updates the relay target (you can have 1 of each type)<br/>Clear will disable them all")]
|
||||||
|
[ReturnHints("cleared")]
|
||||||
|
[ReturnHints("set/avatar [ok]")]
|
||||||
|
[ReturnHints("set/http [ok]")]
|
||||||
|
[ReturnHints("set/channel [ok]")]
|
||||||
|
[ReturnHintsFailure("Not a vaild option")]
|
||||||
|
[ArgHints("target","URLARG", "Options: Channel (Any number),Avatar UUID,HTTPurl<br/>Clear")]
|
||||||
|
[Route(HttpVerbs.Get, "/DialogRelay/{target}/{token}")]
|
||||||
|
public object DialogRelay(string target,string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (target == "clear")
|
||||||
|
{
|
||||||
|
bot.SetRelayDialogsAvatar(UUID.Zero);
|
||||||
|
bot.SetRelayDialogsChannel(0);
|
||||||
|
bot.SetRelayDialogsHTTP("");
|
||||||
|
return BasicReply("cleared", "DialogRelay", new [] { target });
|
||||||
|
}
|
||||||
|
ProcessAvatar(target);
|
||||||
|
if (avataruuid != UUID.Zero)
|
||||||
|
{
|
||||||
|
bot.SetRelayDialogsAvatar(avataruuid);
|
||||||
|
return BasicReply("set/avatar [ok]", "DialogRelay", new [] { target });
|
||||||
|
}
|
||||||
|
if (target.StartsWith("http") == true)
|
||||||
|
{
|
||||||
|
bot.SetRelayDialogsHTTP(target);
|
||||||
|
return BasicReply("set/http [ok]", "DialogRelay", new [] { target });
|
||||||
|
}
|
||||||
|
if (int.TryParse(target, out int channel) == true)
|
||||||
|
{
|
||||||
|
bot.SetRelayDialogsChannel(channel);
|
||||||
|
return BasicReply("set/channel [ok]", "DialogRelay", new [] { target });
|
||||||
|
}
|
||||||
|
return Failure("Not a vaild option", "DialogRelay", new [] { target });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Makes the bot interact with the dialog [dialogid] with the button [buttontext]")]
|
||||||
|
[ReturnHints("true")]
|
||||||
|
[ReturnHints("false")]
|
||||||
|
[ReturnHintsFailure("bad dialog id")]
|
||||||
|
[ArgHints("dialogid", "URLARG", "The ID for the dialog")]
|
||||||
|
[ArgHints("buttontext", "URLARG", "The button text to push")]
|
||||||
|
[Route(HttpVerbs.Get, "/DialogResponce/{dialogid}/{buttontext}/{token}")]
|
||||||
|
public object DialogResponce(string dialogid, string buttontext, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (int.TryParse(dialogid, out int dialogidnum) == false)
|
||||||
|
{
|
||||||
|
return Failure("bad dialog id", "DialogResponce", new [] { dialogid, buttontext });
|
||||||
|
}
|
||||||
|
return BasicReply(bot.DialogReply(dialogidnum, buttontext).ToString(), "DialogResponce", new [] { dialogid, buttontext });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Should the bot track dialogs and send them to the relays setup?")]
|
||||||
|
[ReturnHints("updated")]
|
||||||
|
[ReturnHintsFailure("bad status")]
|
||||||
|
[ArgHints("status", "URLARG", "true or false")]
|
||||||
|
[Route(HttpVerbs.Get, "/DialogTrack/{status}/{token}")]
|
||||||
|
public object DialogTrack(string status, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bool.TryParse(status, out bool statuscode) == false)
|
||||||
|
{
|
||||||
|
return Failure("bad status", "DialogTrack", new [] { status });
|
||||||
|
}
|
||||||
|
bot.SetTrackDialogs(statuscode);
|
||||||
|
return BasicReply("updated", "DialogTrack", new [] { status });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
710
SecondBotEvents/Commands/Discord.cs
Normal file
710
SecondBotEvents/Commands/Discord.cs
Normal file
|
|
@ -0,0 +1,710 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Discord : CommandsAPI
|
||||||
|
{
|
||||||
|
public Discord(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
[About("Adds a discord server role to the selected member")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ArgHints("serverid","URLARG","the server id to apply this action to")]
|
||||||
|
[ArgHints("roleid", "URLARG", "the role id we are giving")]
|
||||||
|
[ArgHints("memberid", "URLARG", "who we are giving it to")]
|
||||||
|
[Route(HttpVerbs.Get, "/Discord_AddRole/{serverid}/{roleid}/{memberid}/{token}")]
|
||||||
|
public object Discord_AddRole(string serverid,string roleid,string memberid,string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_AddRole", new [] { serverid, roleid, memberid });
|
||||||
|
}
|
||||||
|
return BasicReply(addRoleToMember(serverid, roleid, memberid).Result.ToString(), "Discord_AddRole", new [] { serverid, roleid, memberid });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Adds the selected user to the ban list - Disallows rejoining untill they are removed from the list")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ReturnHintsFailure("Why empty")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[ArgHints("memberid", "URLARG", "who we are giving it to")]
|
||||||
|
[ArgHints("why", "string", "why they are being banned")]
|
||||||
|
[Route(HttpVerbs.Post, "/Discord_BanMember/{serverid}/{memberid}/{token}")]
|
||||||
|
public object Discord_BanMember(string serverid, string memberid, [FormField] string why, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_BanMember", new [] { serverid, memberid, why });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(why) == false)
|
||||||
|
{
|
||||||
|
return Failure("Why empty", "Discord_BanMember", new [] { serverid, memberid, why });
|
||||||
|
}
|
||||||
|
return BasicReply(BanMember(serverid, memberid, why).Result.ToString(), "Discord_BanMember", new [] { serverid, memberid, why });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Clears messages on the server sent by the member in the last 13 days, 22hours 59mins")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[ArgHints("memberid", "URLARG", "who we are giving it to")]
|
||||||
|
[Route(HttpVerbs.Get, "/Discord_BulkClear_Messages/{serverid}/{memberid}/{token}")]
|
||||||
|
public object Discord_BulkClear_Messages(string serverid, string memberid, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_BulkClear_Messages", new [] { serverid, memberid });
|
||||||
|
}
|
||||||
|
SuccessNoReturn("Discord_BulkClear_Messages", new [] { serverid, memberid });
|
||||||
|
return ClearMessages(serverid, memberid).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sends a message directly to the user [They must be in the server]\n This command requires the SERVER MEMBERS INTENT found in discord app dev")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[ArgHints("memberid", "URLARG", "who we are giving it to")]
|
||||||
|
[ArgHints("message", "Text", "what we are sending")]
|
||||||
|
[Route(HttpVerbs.Post, "/Discord_Dm_Member/{serverid}/{memberid}/{token}")]
|
||||||
|
public object Discord_Dm_Member(string serverid, string memberid, [FormField] string message, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_Dm_Member", new [] { serverid, memberid, message });
|
||||||
|
}
|
||||||
|
return BasicReply(MessageMember(serverid, memberid, message).Result.ToString(), "Discord_Dm_Member", new [] { serverid, memberid, message });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Returns a list of members in a server \n collection is userid: username \n if the user has set a nickname: userid: nickname|username \n" +
|
||||||
|
" This command requires Discord full client mode enabled and connected\n !!!! This command also requires: Privileged Gateway Intents / " +
|
||||||
|
"SERVER MEMBERS INTENT set to true on the discord bot api area !!!")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ReturnHints("mixed array of userid: nickname|username or userid:username")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[Route(HttpVerbs.Get, "/Discord_MembersList/{serverid}/{token}")]
|
||||||
|
public object Discord_MembersList(string serverid, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_MembersList", new [] { serverid });
|
||||||
|
}
|
||||||
|
SuccessNoReturn("Discord_MembersList", new [] { serverid });
|
||||||
|
return ListMembers(serverid).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sends a message to the selected channel - Optional TTS usage")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ReturnHintsFailure("message empty")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[ArgHints("channelid", "URLARG", "the channel id to apply this action to")]
|
||||||
|
[ArgHints("tts", "URLARG", "shoud tts be enabled true or false")]
|
||||||
|
[ArgHints("message", "Text", "what we are sending")]
|
||||||
|
[Route(HttpVerbs.Post, "/Discord_MembersList/{serverid}/{tts}/{token}")]
|
||||||
|
public object Discord_MessageChannel(string serverid, string channelid, string tts, [FormField] string message, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_MessageChannel", new [] { serverid, channelid, tts, message });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(message) == false)
|
||||||
|
{
|
||||||
|
return Failure("message empty", "Discord_MessageChannel", new [] { serverid, channelid, tts, message });
|
||||||
|
}
|
||||||
|
return BasicReply(MessageChannel(serverid, channelid, message, tts).Result.ToString(), "Discord_MessageChannel", new [] { serverid, channelid, tts, message });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sends a message to the selected channel - Optional TTS usage")]
|
||||||
|
[ReturnHints("mixed array of userid: nickname|username or userid:username")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[ArgHints("memberid", "URLARG", "who we are giving it to")]
|
||||||
|
[ArgHints("mode", "URLARG", "should we mute them \"true\" or unmute \"false\"")]
|
||||||
|
[Route(HttpVerbs.Get, "/Discord_MuteMember/{serverid}/{memberid}/{mode}/{token}")]
|
||||||
|
public object Discord_MuteMember(string serverid, string memberid, string mode, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_MuteMember", new [] { serverid, memberid, mode });
|
||||||
|
}
|
||||||
|
return BasicReply(MuteMember(serverid, memberid, mode).Result.ToString(), "Discord_MuteMember", new [] { serverid, memberid, mode });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("returns a collection of settings for the given role \n This command requires Discord full client mode enabled and connected")]
|
||||||
|
[ReturnHints("KeyPair of status: KeyPair[] item = value")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[ArgHints("memberid", "URLARG", "who we are giving it to")]
|
||||||
|
[ArgHints("mode", "URLARG", "should we mute them \"true\" or unmute \"false\"")]
|
||||||
|
[Route(HttpVerbs.Get, "/Discord_Role_GetSettings/{serverid}/{roleid}/{token}")]
|
||||||
|
public object Discord_Role_GetSettings(string serverid, string roleid, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_Role_GetSettings", new [] { serverid, roleid });
|
||||||
|
}
|
||||||
|
SuccessNoReturn("Discord_Role_GetSettings", new [] { serverid, roleid });
|
||||||
|
return RoleSettings(serverid,roleid);
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Updates perm flags for the selected role \n example CSV format: Speak=True,SendMessages=False \n for a full list of perms see output of Discord_Role_GetSettings \n" +
|
||||||
|
" This command requires Discord full client mode enabled and connected")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[ArgHints("roleid", "URLARG", "who we are giving it to")]
|
||||||
|
[ArgHints("flagscsv", "Text", "what we are setting")]
|
||||||
|
[Route(HttpVerbs.Post, "/Discord_Role_UpdatePerms/{serverid}/{roleid}/{token}")]
|
||||||
|
public object Discord_Role_UpdatePerms(string serverid, string roleid, [FormField] string flagscsv, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_Role_UpdatePerms", new [] { serverid, roleid, flagscsv });
|
||||||
|
}
|
||||||
|
return BasicReply(UpdateRolePerms(serverid, roleid, flagscsv).Result.ToString(), "Discord_Role_UpdatePerms", new [] { serverid, roleid, flagscsv });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Updates perm flags for the selected role \n example CSV format: Speak=True,SendMessages=False \n for a full list of perms see output of Discord_Role_GetSettings \n" +
|
||||||
|
" This command requires Discord full client mode enabled and connected")]
|
||||||
|
[ReturnHints("KeyPair of statusmessage=roleid or 0")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[ArgHints("role", "URLARG", "the name of the role we are creating")]
|
||||||
|
[Route(HttpVerbs.Get, "/Discord_RoleCreate/{serverid}/{role}/{token}")]
|
||||||
|
public object Discord_RoleCreate(string serverid, string role, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_RoleCreate", new [] { serverid, role });
|
||||||
|
}
|
||||||
|
SuccessNoReturn("Discord_RoleCreate", new [] { serverid, role });
|
||||||
|
return CreateRole(serverid,role).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Returns a list of roles and their ids in collection \n This command requires Discord full client mode enabled and connected")]
|
||||||
|
[ReturnHints("KeyPair of status: KeyPair of roleid: rolename")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[Route(HttpVerbs.Get, "/Discord_RoleList/{serverid}/{token}")]
|
||||||
|
public object Discord_RoleList(string serverid, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_RoleList", new [] { serverid });
|
||||||
|
}
|
||||||
|
return BasicReply(ListRoles(serverid).ToString(), "Discord_RoleList", new [] { serverid });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Remove a role from a server \n This command requires Discord full client mode enabled and connected")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[Route(HttpVerbs.Get, "/Discord_RoleRemove/{serverid}/{roleid}/{token}")]
|
||||||
|
public object Discord_RoleRemove(string serverid, string roleid, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_RoleRemove", new [] { serverid, roleid });
|
||||||
|
}
|
||||||
|
return BasicReply(RemoveRole(serverid, roleid).Result.ToString(), "Discord_RoleRemove", new [] { serverid, roleid });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Returns a list of text channels in a server")]
|
||||||
|
[ReturnHints("array of channelid: name")]
|
||||||
|
[ReturnHintsFailure("Discord client not ready")]
|
||||||
|
[ArgHints("serverid", "URLARG", "the server id to apply this action to")]
|
||||||
|
[Route(HttpVerbs.Get, "/Discord_TextChannels_List/{serverid}/{roleid}/{token}")]
|
||||||
|
public object Discord_TextChannels_List(string serverid, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.discordReady() == false)
|
||||||
|
{
|
||||||
|
return Failure("Discord client not ready", "Discord_TextChannels_List", new [] { serverid });
|
||||||
|
}
|
||||||
|
return ListTextChannels(serverid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region discord helper functions
|
||||||
|
|
||||||
|
protected KeyValuePair<bool, Dictionary<string, string>> ListTextChannels(string givenserverid)
|
||||||
|
{
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == true)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<bool, Dictionary<string, string>>(false, new Dictionary<string, string>());
|
||||||
|
}
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
Dictionary<string, string> textChannels = new Dictionary<string, string>();
|
||||||
|
foreach (SocketTextChannel channel in server.TextChannels)
|
||||||
|
{
|
||||||
|
textChannels.Add(channel.Id.ToString(), channel.Name);
|
||||||
|
}
|
||||||
|
return new KeyValuePair<bool, Dictionary<string, string>>(true, textChannels);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<bool> RemoveRole(string givenserverid, string givenroleid)
|
||||||
|
{
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ulong.TryParse(givenroleid, out ulong roleid) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
SocketRole role = server.GetRole(roleid);
|
||||||
|
await role.DeleteAsync().ConfigureAwait(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected KeyValuePair<bool, Dictionary<string, string>> ListRoles(string givenserverid)
|
||||||
|
{
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == false)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<bool, Dictionary<string, string>>(false, new Dictionary<string, string>());
|
||||||
|
}
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
Dictionary<string, string> rolesList = new Dictionary<string, string>();
|
||||||
|
foreach (SocketRole role in server.Roles)
|
||||||
|
{
|
||||||
|
rolesList.Add(role.Id.ToString(), role.Name);
|
||||||
|
}
|
||||||
|
return new KeyValuePair<bool, Dictionary<string, string>>(true, rolesList);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<KeyValuePair<string, ulong>> CreateRole(string givenserverid, string givenrole)
|
||||||
|
{
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == true)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<string, ulong>("Unable to process server id", 0);
|
||||||
|
}
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
RestRole role = await server.CreateRoleAsync(givenrole, new GuildPermissions(), Color.DarkRed, false, null).ConfigureAwait(true);
|
||||||
|
return new KeyValuePair<string, ulong>("ok", role.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<bool> UpdateRolePerms(string givenserverid,string givenroleid,string givenflagscsv)
|
||||||
|
{
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ulong.TryParse(givenroleid, out ulong roleid) == true)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
SocketRole role = server.GetRole(roleid);
|
||||||
|
string[] bits = givenflagscsv.Split(',');
|
||||||
|
GuildPermissions NewPerms = role.Permissions;
|
||||||
|
foreach (String bit in bits)
|
||||||
|
{
|
||||||
|
string[] subbits = bit.Split('=');
|
||||||
|
if (subbits.Length == 2)
|
||||||
|
{
|
||||||
|
if (bool.TryParse(subbits[1], out bool flagValue) == true)
|
||||||
|
{
|
||||||
|
NewPerms = UpdateFlag(NewPerms, subbits[0], flagValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await role.ModifyAsync(Rp =>
|
||||||
|
{
|
||||||
|
Rp.Permissions = NewPerms;
|
||||||
|
}).ConfigureAwait(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GuildPermissions UpdateFlag(GuildPermissions NewPerms, string flag, bool flagValue)
|
||||||
|
{
|
||||||
|
switch (flag)
|
||||||
|
{
|
||||||
|
case "CreateInstantInvite":
|
||||||
|
NewPerms = NewPerms.Modify(flagValue);
|
||||||
|
break;
|
||||||
|
case "KickMembers":
|
||||||
|
NewPerms = NewPerms.Modify(null, flagValue);
|
||||||
|
break;
|
||||||
|
case "BanMembers":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "Administrator":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "ManageChannels":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "ManageGuild":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "AddReactions":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "ViewAuditLog":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "SendTTSMessages":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "AttachFiles":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "ReadMessageHistory":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "MentionEveryone":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "UseExternalEmojis":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "Connect":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "Speak":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "MuteMembers":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "UseVAD":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "MoveMembers":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "EmbedLinks":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "PrioritySpeaker":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "Stream":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "ChangeNickname":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "ManageNicknames":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "ManageRoles":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "DeafenMembers":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "ManageMessages":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "ViewChannel":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "SendMessages":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "ManageWebhooks":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
case "ManageEmojis":
|
||||||
|
NewPerms = NewPerms.Modify(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, flagValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NewPerms;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected KeyValuePair<bool, Dictionary<string, string>> RoleSettings(string givenserverid, string givenroleid)
|
||||||
|
{
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == false)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<bool, Dictionary<string, string>>(false, new Dictionary<string, string>());
|
||||||
|
}
|
||||||
|
if (ulong.TryParse(givenroleid, out ulong roleid) == false)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<bool, Dictionary<string, string>>(false, new Dictionary<string, string>());
|
||||||
|
}
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
SocketRole role = server.GetRole(roleid);
|
||||||
|
Dictionary<string, string> settings = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "Config|Color", String.Join(",", new byte[3] { role.Color.R, role.Color.G, role.Color.B }) },
|
||||||
|
{ "Config|Name", role.Name },
|
||||||
|
{ "Info|AssignedCount", role.Members.ToString() },
|
||||||
|
{ "Perm|AttachFiles", role.Permissions.AttachFiles.ToString() },
|
||||||
|
{ "Perm|ReadMessageHistory", role.Permissions.ReadMessageHistory.ToString() },
|
||||||
|
{ "Perm|MentionEveryone", role.Permissions.MentionEveryone.ToString() },
|
||||||
|
{ "Perm|UseExternalEmojis", role.Permissions.UseExternalEmojis.ToString() },
|
||||||
|
{ "Perm|Connect", role.Permissions.Connect.ToString() },
|
||||||
|
{ "Perm|Speak", role.Permissions.Speak.ToString() },
|
||||||
|
{ "Perm|MuteMembers", role.Permissions.MuteMembers.ToString() },
|
||||||
|
{ "Perm|UseVAD", role.Permissions.UseVAD.ToString() },
|
||||||
|
{ "Perm|MoveMembers", role.Permissions.MoveMembers.ToString() },
|
||||||
|
{ "Perm|EmbedLinks", role.Permissions.EmbedLinks.ToString() },
|
||||||
|
{ "Perm|PrioritySpeaker", role.Permissions.PrioritySpeaker.ToString() },
|
||||||
|
{ "Perm|Stream", role.Permissions.Stream.ToString() },
|
||||||
|
{ "Perm|ChangeNickname", role.Permissions.ChangeNickname.ToString() },
|
||||||
|
{ "Perm|ManageNicknames", role.Permissions.ManageNicknames.ToString() },
|
||||||
|
{ "Perm|ManageRoles", role.Permissions.ManageRoles.ToString() },
|
||||||
|
{ "Perm|DeafenMembers", role.Permissions.DeafenMembers.ToString() },
|
||||||
|
{ "Perm|ManageMessages", role.Permissions.ManageMessages.ToString() },
|
||||||
|
{ "Perm|ViewChannel", role.Permissions.ViewChannel.ToString() },
|
||||||
|
{ "Perm|SendMessages", role.Permissions.SendMessages.ToString() },
|
||||||
|
{ "Perm|CreateInstantInvite", role.Permissions.CreateInstantInvite.ToString() },
|
||||||
|
{ "Perm|BanMembers", role.Permissions.BanMembers.ToString() },
|
||||||
|
{ "Perm|SendTTSMessages", role.Permissions.SendTTSMessages.ToString() },
|
||||||
|
{ "Perm|Administrator", role.Permissions.Administrator.ToString() },
|
||||||
|
{ "Perm|ManageChannels", role.Permissions.ManageChannels.ToString() },
|
||||||
|
{ "Perm|KickMembers", role.Permissions.KickMembers.ToString() },
|
||||||
|
{ "Perm|AddReactions", role.Permissions.AddReactions.ToString() },
|
||||||
|
{ "Perm|ViewAuditLog", role.Permissions.ViewAuditLog.ToString() },
|
||||||
|
{ "Perm|ManageWebhooks", role.Permissions.ManageWebhooks.ToString() },
|
||||||
|
{ "Perm|ManageGuild", role.Permissions.ManageGuild.ToString() },
|
||||||
|
{ "Perm|ManageEmojis", role.Permissions.ManageEmojis.ToString() }
|
||||||
|
};
|
||||||
|
return new KeyValuePair<bool, Dictionary<string, string>>(true, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<bool> MuteMember(string givenserverid, string givenmemberid, string mode)
|
||||||
|
{
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == true)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ulong.TryParse(givenmemberid, out ulong memberid) == true)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
SocketGuildUser user = server.GetUser(memberid);
|
||||||
|
bool.TryParse(mode, out bool status);
|
||||||
|
await user.ModifyAsync(pr =>
|
||||||
|
{
|
||||||
|
pr.Mute = status;
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<bool> MessageChannel(string givenserverid, string givenchannelid, string givenmessage, string tts)
|
||||||
|
{
|
||||||
|
if (bool.TryParse(tts, out bool useTTS) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return await bot.SendMessageToDiscord(givenserverid, givenchannelid, givenmessage, useTTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected async Task<KeyValuePair<bool, Dictionary<string, string>>> ListMembers(string givenserverid)
|
||||||
|
{
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == false)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<bool, Dictionary<string, string>>(false, new Dictionary<string, string>());
|
||||||
|
}
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
IEnumerable<IGuildUser> users = await server.GetUsersAsync().FlattenAsync().ConfigureAwait(true);
|
||||||
|
Dictionary<string, string> membersList = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
foreach (IGuildUser user in users)
|
||||||
|
{
|
||||||
|
if (user.Nickname != null)
|
||||||
|
{
|
||||||
|
membersList.Add(user.Id.ToString(), user.Nickname + "|" + user.Username);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
membersList.Add(user.Id.ToString(), user.Username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new KeyValuePair<bool, Dictionary<string, string>>(true, membersList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected async Task<bool> MessageMember(string givenserverid, string givenmemberid, string givenmessage)
|
||||||
|
{
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ulong.TryParse(givenmemberid, out ulong memberid) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
IEnumerable<IGuildUser> users = await server.GetUsersAsync().FlattenAsync().ConfigureAwait(true);
|
||||||
|
bool sent = false;
|
||||||
|
foreach (IGuildUser user in users)
|
||||||
|
{
|
||||||
|
if (user.Id == memberid)
|
||||||
|
{
|
||||||
|
sent = true;
|
||||||
|
await user.SendMessageAsync(givenmessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<KeyValuePair<bool, int>> ClearMessages(string givenserverid, string givenmemberid)
|
||||||
|
{
|
||||||
|
int messagesDeleted = 0;
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == false)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<bool, int>(false, 0);
|
||||||
|
}
|
||||||
|
if (ulong.TryParse(givenmemberid, out ulong memberid) == false)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<bool, int>(false, 0);
|
||||||
|
}
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
SocketGuildUser user = server.GetUser(memberid);
|
||||||
|
TimeSpan somedays = new TimeSpan(13, 22, 59, 59, 0);
|
||||||
|
DateTimeOffset justundertwosweeks = DateTimeOffset.Now;
|
||||||
|
justundertwosweeks = justundertwosweeks.Subtract(somedays);
|
||||||
|
long unixtimelimit = justundertwosweeks.ToUnixTimeSeconds();
|
||||||
|
foreach (SocketTextChannel channel in server.TextChannels)
|
||||||
|
{
|
||||||
|
List<IMessage> DeleteMessages = new List<IMessage>();
|
||||||
|
IEnumerable<IMessage> messages = await channel.GetMessagesAsync(100).FlattenAsync();
|
||||||
|
foreach (IMessage message in messages)
|
||||||
|
{
|
||||||
|
if (message.CreatedAt.ToUnixTimeSeconds() > unixtimelimit)
|
||||||
|
{
|
||||||
|
if (message.Author.Id == user.Id)
|
||||||
|
{
|
||||||
|
DeleteMessages.Add(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (DeleteMessages.Count > 0)
|
||||||
|
{
|
||||||
|
messagesDeleted += DeleteMessages.Count;
|
||||||
|
await channel.DeleteMessagesAsync(DeleteMessages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new KeyValuePair<bool, int>(true, messagesDeleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected async Task<bool> BanMember(string givenserverid, string givenmemberid, string why)
|
||||||
|
{
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ulong.TryParse(givenmemberid, out ulong memberid) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
SocketGuildUser user = server.GetUser(memberid);
|
||||||
|
await user.BanAsync(7, why);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected async Task<bool> addRoleToMember(string givenserverid, string givenroleid, string givenmemberid)
|
||||||
|
{
|
||||||
|
DiscordSocketClient Discord = bot.getDiscordClient();
|
||||||
|
if (ulong.TryParse(givenserverid, out ulong serverid) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ulong.TryParse(givenroleid, out ulong roleid) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ulong.TryParse(givenmemberid, out ulong memberid) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SocketGuild server = Discord.GetGuild(serverid);
|
||||||
|
SocketRole role = server.GetRole(roleid);
|
||||||
|
SocketGuildUser user = server.GetUser(memberid);
|
||||||
|
await user.AddRoleAsync(role); // ? Irole seems to accept SocketRole ?
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
184
SecondBotEvents/Commands/Estate.cs
Normal file
184
SecondBotEvents/Commands/Estate.cs
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Estate : CommandsAPI
|
||||||
|
{
|
||||||
|
public Estate(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
[About("Sends the message to the current sim")]
|
||||||
|
[ReturnHints("restarting")]
|
||||||
|
[ReturnHintsFailure("Not an estate manager here")]
|
||||||
|
[ReturnHintsFailure("canceled")]
|
||||||
|
[ArgHints("delay", "URLARG", "How long to delay the restart for (30 to 240 secs) - defaults to 240 if out of bounds \n" +
|
||||||
|
"set to 0 if your canceling!")]
|
||||||
|
[ArgHints("mode", "URLARG", "true to start a restart, false to cancel")]
|
||||||
|
[Route(HttpVerbs.Get, "/SimRestart/{delay}/{mode}/{token}")]
|
||||||
|
public object SimRestart(string delay, string mode, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (getClient().Network.CurrentSim.IsEstateManager == false)
|
||||||
|
{
|
||||||
|
return Failure("Not an estate manager here", "SimRestart", new [] { delay, mode });
|
||||||
|
}
|
||||||
|
bool.TryParse(mode, out bool modeflag);
|
||||||
|
if (modeflag == false)
|
||||||
|
{
|
||||||
|
getClient().Estate.CancelRestart();
|
||||||
|
return BasicReply("canceled", "SimRestart", new [] { delay, mode });
|
||||||
|
}
|
||||||
|
int delay_restart = 60;
|
||||||
|
int.TryParse(delay, out delay_restart);
|
||||||
|
if((delay_restart < 30) || (delay_restart > 240))
|
||||||
|
{
|
||||||
|
delay_restart = 240;
|
||||||
|
}
|
||||||
|
getClient().Estate.RestartRegion(delay_restart);
|
||||||
|
return BasicReply("restarting", "SimRestart", new [] { delay, mode });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sends the message to the current sim")]
|
||||||
|
[ReturnHintsFailure("Not an estate manager here")]
|
||||||
|
[ReturnHintsFailure("Message empty")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ArgHints("message", "Text", "What the message is")]
|
||||||
|
[Route(HttpVerbs.Post, "/SimMessage/{token}")]
|
||||||
|
public object SimMessage([FormField] string message, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(message) == false)
|
||||||
|
{
|
||||||
|
return Failure("Message empty", "SimMessage", new [] { message });
|
||||||
|
}
|
||||||
|
if (getClient().Network.CurrentSim.IsEstateManager == false)
|
||||||
|
{
|
||||||
|
return Failure("Not an estate manager here", "SimMessage", new [] { message });
|
||||||
|
}
|
||||||
|
getClient().Estate.SimulatorMessage(message);
|
||||||
|
return BasicReply("ok", "SimMessage", new [] { message });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Fetchs the regions map tile")]
|
||||||
|
[ReturnHintsFailure("Unable to find region")]
|
||||||
|
[ReturnHints("Texture UUID")]
|
||||||
|
[ArgHints("regionname", "URLARG", "the name of the region we are fetching")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetSimTexture/{regionname}/{token}")]
|
||||||
|
public object GetSimTexture(string regionname, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (getClient().Grid.GetGridRegion(regionname, GridLayerType.Objects, out GridRegion region) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unable to find region", "GetSimTexture", new [] { regionname });
|
||||||
|
}
|
||||||
|
return BasicReply(region.MapImageID.ToString(), "GetSimTexture", new [] { regionname });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Reclaims ownership of the current parcel")]
|
||||||
|
[ReturnHintsFailure("Not an estate manager here")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[Route(HttpVerbs.Get, "/EstateParcelReclaim/{token}")]
|
||||||
|
public object EstateParcelReclaim(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (getClient().Network.CurrentSim.IsEstateManager == false)
|
||||||
|
{
|
||||||
|
return Failure("Not an estate manager here", "EstateParcelReclaim");
|
||||||
|
}
|
||||||
|
int localid = getClient().Parcels.GetParcelLocalID(getClient().Network.CurrentSim, getClient().Self.SimPosition);
|
||||||
|
getClient().Parcels.Reclaim(getClient().Network.CurrentSim, localid);
|
||||||
|
return BasicReply("ok", "EstateParcelReclaim");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Reclaims ownership of the current parcel")]
|
||||||
|
[ReturnHintsFailure("Not an estate manager here")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetSimGlobalPos/{regionname}/{token}")]
|
||||||
|
public object GetSimGlobalPos(string regionname, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (getClient().Grid.GetGridRegion(regionname, GridLayerType.Objects, out GridRegion region) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unable to find region", "GetSimGlobalPos", new [] { regionname });
|
||||||
|
}
|
||||||
|
Dictionary<string, string> reply = new Dictionary<string, string>();
|
||||||
|
reply.Add("region", regionname);
|
||||||
|
reply.Add("X", region.X.ToString());
|
||||||
|
reply.Add("Y", region.Y.ToString());
|
||||||
|
SuccessNoReturn("GetSimGlobalPos", new [] { regionname });
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Requests the estate banlist")]
|
||||||
|
[ReturnHints("ban list json")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetEstateBanList/{token}")]
|
||||||
|
public object GetEstateBanList(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(bot._lastUpdatedSimBlacklist), "banlist");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Attempts to add/remove the avatar to/from the Estate banlist")]
|
||||||
|
[ReturnHints("Unban request accepted")]
|
||||||
|
[ReturnHints("Ban request accepted")]
|
||||||
|
[ReturnHintsFailure("Unable to find avatar UUID")]
|
||||||
|
[ReturnHintsFailure("Unable to process global value please use true or false")]
|
||||||
|
[ReturnHintsFailure("Not an estate manager on region {REGIONNAME}")]
|
||||||
|
[ArgHints("avatar", "URLARG", "the uuid avatar you wish to ban")]
|
||||||
|
[ArgHints("mode", "URLARG", "What action would you like to take<br/>Defaults to remove if not given \"add\"")]
|
||||||
|
[ArgHints("global", "URLARG", "if true this the ban/unban will be applyed to all estates the bot has access to")]
|
||||||
|
[Route(HttpVerbs.Get, "/UpdateEstateBanlist/{avatar}/{mode}/{global}/{token}")]
|
||||||
|
|
||||||
|
public object UpdateEstateBanlist(string avatar, string mode, string global, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (getClient().Network.CurrentSim.IsEstateManager == false)
|
||||||
|
{
|
||||||
|
return Failure("Not an estate manager on region " + getClient().Network.CurrentSim.Name, "UpdateEstateBanlist", new [] { avatar, mode, global });
|
||||||
|
}
|
||||||
|
UUID avataruuid = UUID.Zero;
|
||||||
|
if (UUID.TryParse(avatar, out avataruuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unable to find avatar UUID", "UpdateEstateBanlist", new [] { avatar, mode, global });
|
||||||
|
}
|
||||||
|
bool globalban = false;
|
||||||
|
if (bool.TryParse(global, out globalban) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unable to process global value please use true or false", "UpdateEstateBanlist", new [] { avatar, mode, global });
|
||||||
|
}
|
||||||
|
if (mode != "add")
|
||||||
|
{
|
||||||
|
getClient().Estate.UnbanUser(avataruuid, globalban);
|
||||||
|
return BasicReply("Unban request accepted", "UpdateEstateBanlist", new [] { avatar, mode, global });
|
||||||
|
}
|
||||||
|
getClient().Estate.BanUser(avataruuid, globalban);
|
||||||
|
return BasicReply("Ban request accepted", "UpdateEstateBanlist", new [] { avatar, mode, global });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
109
SecondBotEvents/Commands/Friends.cs
Normal file
109
SecondBotEvents/Commands/Friends.cs
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Friends : CommandsAPI
|
||||||
|
{
|
||||||
|
public Friends(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
[About("Gets the friendslist <br/>Formated as follows<br/>friendreplyobject<br/><ul><li>name: String</li><li>id: String</li><li>online: bool</li></ul>")]
|
||||||
|
[ReturnHints("array UUID = friendreplyobject")]
|
||||||
|
[Route(HttpVerbs.Get, "/Friendslist/{token}")]
|
||||||
|
public object Friendslist(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
return BasicReply(bot.getJsonFriendlist(), "Friendslist");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Updates the friend perms for avatar avatar to State \n if true grants (Online/Map/Modify) perms")]
|
||||||
|
[ArgHints("avatar", "URLARG", "A avatar uuid or Firstname Lastname")]
|
||||||
|
[ArgHints("state", "URLARG", "true: Grant perms, false: Remove perms")]
|
||||||
|
[ReturnHints("granted")]
|
||||||
|
[ReturnHints("removed")]
|
||||||
|
[ReturnHintsFailure("Not A friend")]
|
||||||
|
[ReturnHintsFailure("state invaild")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[Route(HttpVerbs.Get, "/FriendFullPerms/{avatar}/{state}/{token}")]
|
||||||
|
public object FriendFullPerms(string avatar, string state, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("avatar lookup", "FriendFullPerms", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
bool status = false;
|
||||||
|
if (bool.TryParse(state, out status) == false)
|
||||||
|
{
|
||||||
|
return Failure("state invaild", "FriendFullPerms", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
if (getClient().Friends.FriendList.ContainsKey(avataruuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Not A friend", "FriendFullPerms", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
if (status == true)
|
||||||
|
{
|
||||||
|
getClient().Friends.GrantRights(avataruuid, FriendRights.CanSeeOnline | FriendRights.CanSeeOnMap | FriendRights.CanModifyObjects);
|
||||||
|
return BasicReply("granted", "FriendFullPerms", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
getClient().Friends.GrantRights(avataruuid, FriendRights.None);
|
||||||
|
return BasicReply("removed", "FriendFullPerms", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Updates the friend perms for avatar avatar to State \n if true grants (Online/Map/Modify) perms")]
|
||||||
|
[ReturnHints("Request sent")]
|
||||||
|
[ReturnHints("Removed")]
|
||||||
|
[ReturnHintsFailure("Already a friend")]
|
||||||
|
[ReturnHintsFailure("Not in friendslist")]
|
||||||
|
[ReturnHintsFailure("state invaild")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[ArgHints("avatar", "URLARG", "A avatar uuid or Firstname Lastname")]
|
||||||
|
[ArgHints("state", "URLARG", "true: Send invite, false: Remove from friendslist")]
|
||||||
|
[Route(HttpVerbs.Get, "/FriendRequest/{avatar}/{state}/{token}")]
|
||||||
|
public object FriendRequest(string avatar, string state, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("avatar lookup", "FriendRequest", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
bool status = false;
|
||||||
|
if (bool.TryParse(state, out status) == false)
|
||||||
|
{
|
||||||
|
return Failure("state invaild", "FriendRequest", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
if (getClient().Friends.FriendList.ContainsKey(avataruuid) == true)
|
||||||
|
{
|
||||||
|
if (status == false)
|
||||||
|
{
|
||||||
|
getClient().Friends.TerminateFriendship(avataruuid);
|
||||||
|
return BasicReply("Removed", "FriendRequest", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (status == false)
|
||||||
|
{
|
||||||
|
return Failure("Not in friendslist", "FriendRequest", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
getClient().Friends.OfferFriendship(avataruuid);
|
||||||
|
return BasicReply("Request sent", "FriendRequest", new [] { avatar, state });
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
109
SecondBotEvents/Commands/Funds.cs
Normal file
109
SecondBotEvents/Commands/Funds.cs
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Funds : CommandsAPI
|
||||||
|
{
|
||||||
|
public Funds(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
[About("Requests the current balance and requests the balance to update.")]
|
||||||
|
[ReturnHints("Current fund level")]
|
||||||
|
[ReturnHintsFailure("Funds commands are disabled")]
|
||||||
|
[Route(HttpVerbs.Get, "/Balance/{token}")]
|
||||||
|
public object Balance(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.GetAllowFunds == false)
|
||||||
|
{
|
||||||
|
return Failure("Funds commands are disabled", "Balance");
|
||||||
|
}
|
||||||
|
getClient().Self.RequestBalance();
|
||||||
|
return BasicReply(getClient().Self.Balance.ToString(), "Balance");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Makes the bot pay a avatar")]
|
||||||
|
[ReturnHints("Accepted")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[ReturnHintsFailure("Amount out of range")]
|
||||||
|
[ReturnHintsFailure("Invaild amount")]
|
||||||
|
[ReturnHintsFailure("Transfer funds to avatars disabled")]
|
||||||
|
[ArgHints("avatar", "URLARG", "the avatars UUID or Firstname Lastname")]
|
||||||
|
[ArgHints("amount", "URLARG", "the amount to pay (from 1 to current balance)")]
|
||||||
|
[Route(HttpVerbs.Get, "/PayAvatar/{avatar}/{amount}/{token}")]
|
||||||
|
public object PayAvatar(string avatar, string amount, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.GetAllowFunds == false)
|
||||||
|
{
|
||||||
|
return Failure("Transfer funds to avatars disabled", "PayAvatar", new [] { avatar, amount });
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return BasicReply("avatar lookup", "PayAvatar", new [] { avatar, amount });
|
||||||
|
}
|
||||||
|
if (int.TryParse(amount, out int amountvalue) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild amount", "PayAvatar", new [] { avatar, amount });
|
||||||
|
}
|
||||||
|
if ((amountvalue < 0) || (amountvalue > getClient().Self.Balance))
|
||||||
|
{
|
||||||
|
return Failure("Amount out of range", "PayAvatar", new [] { avatar, amount });
|
||||||
|
}
|
||||||
|
getClient().Self.GiveAvatarMoney(avataruuid, amountvalue);
|
||||||
|
return BasicReply("Accepted", "PayAvatar", new [] { avatar, amount });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Makes the bot pay a object")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Primname is empty")]
|
||||||
|
[ReturnHintsFailure("Invaild object UUID")]
|
||||||
|
[ReturnHintsFailure("Invaild amount")]
|
||||||
|
[ReturnHintsFailure("Amount out of range")]
|
||||||
|
[ReturnHintsFailure("Funds commands are disabled")]
|
||||||
|
[ArgHints("object", "URLARG", "UUID of the object to pay")]
|
||||||
|
[ArgHints("primname", "URLARG", "The name of the prim on the object to pay")]
|
||||||
|
[ArgHints("amount", "URLARG", "the amount to pay (from 1 to current balance)")]
|
||||||
|
[Route(HttpVerbs.Get, "/PayObject/{object}/{primname}/{amount}/{token}")]
|
||||||
|
public object PayObject(string objectuuid,string primname,string amount,string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.GetAllowFunds == false)
|
||||||
|
{
|
||||||
|
return Failure("Funds commands are disabled", "PayObject", new [] { objectuuid, primname, amount });
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(objectuuid, out UUID objectUUID) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild object UUID", "PayObject", new [] { objectuuid, primname, amount });
|
||||||
|
}
|
||||||
|
if (int.TryParse(amount, out int amountvalue) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild amount", "PayObject", new [] { objectuuid, primname, amount });
|
||||||
|
}
|
||||||
|
if((amountvalue < 0) || (amountvalue > getClient().Self.Balance))
|
||||||
|
{
|
||||||
|
return Failure("Amount out of range", "PayObject", new [] { objectuuid, primname, amount });
|
||||||
|
}
|
||||||
|
if(SecondbotHelpers.notempty(primname) == false)
|
||||||
|
{
|
||||||
|
return Failure("Primname is empty", "PayObject", new [] { objectuuid, primname, amount });
|
||||||
|
}
|
||||||
|
getClient().Self.GiveObjectMoney(objectUUID, amountvalue, primname);
|
||||||
|
return BasicReply("ok", "PayObject", new [] { objectuuid, primname, amount });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
694
SecondBotEvents/Commands/Group.cs
Normal file
694
SecondBotEvents/Commands/Group.cs
Normal file
|
|
@ -0,0 +1,694 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Group : CommandsAPI
|
||||||
|
{
|
||||||
|
public Group(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Checks if the given UUID is in the given group<br/>Note: if group membership data is more than 60 secs old this will return Updating<br/>Please wait and retry later")]
|
||||||
|
[ReturnHints("Membership reply with [membershipStatus,AvatarUUID,AvatarnameIfKnown,GroupUUID]")]
|
||||||
|
[ReturnHintsFailure("Updating")]
|
||||||
|
[ReturnHintsFailure("Unknown group")]
|
||||||
|
[ReturnHintsFailure("Invaild group UUID")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[ArgHints("avatar", "URLARG", "the UUID of the avatar you wish to check with")]
|
||||||
|
[Route(HttpVerbs.Get, "/IsGroupMember/{group}/{avatar}/{token}")]
|
||||||
|
public object IsGroupMember(string group, string avatar, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group UUID", "IsGroupMember", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "IsGroupMember", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
if (bot.NeedReloadGroupData(groupuuid) == true)
|
||||||
|
{
|
||||||
|
getClient().Groups.RequestGroupMembers(groupuuid);
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
KeyValuePair<bool, string> reply = waitForReady(true, true, groupuuid);
|
||||||
|
if (reply.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(reply.Value, "IsGroupMember", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
IsGroupMemberReply replyobject = new IsGroupMemberReply();
|
||||||
|
replyobject.membershipStatus = bot.FastCheckInGroup(groupuuid, avataruuid);
|
||||||
|
replyobject.AvatarUUID = avataruuid.ToString();
|
||||||
|
replyobject.AvatarnameIfKnown = bot.FindAvatarKey2Name(avataruuid);
|
||||||
|
replyobject.GroupUUID = groupuuid.ToString();
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(replyobject), "IsGroupMember", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Gets membership of a group")]
|
||||||
|
[ReturnHints("list of UUIDS of group members")]
|
||||||
|
[ReturnHintsFailure("Updating")]
|
||||||
|
[ReturnHintsFailure("Unknown group")]
|
||||||
|
[ReturnHintsFailure("Invaild group UUID")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetGroupMembers/{group}/{token}")]
|
||||||
|
public object GetGroupMembers(string group, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group UUID", "GetGroupMembers", new [] { group });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "GetGroupMembers", new [] { group });
|
||||||
|
}
|
||||||
|
if (bot.NeedReloadGroupData(groupuuid) == true)
|
||||||
|
{
|
||||||
|
getClient().Groups.RequestGroupMembers(groupuuid);
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> reply = waitForReady(false, true, groupuuid);
|
||||||
|
if (reply.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(reply.Value, "GetGroupMembers", new [] { group });
|
||||||
|
}
|
||||||
|
SuccessNoReturn("GetGroupMembers", new [] { group });
|
||||||
|
return bot.GetGroupMembers(groupuuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Attempts to ban/unban a given avatar from a group")]
|
||||||
|
[ReturnHints("? request accepted")]
|
||||||
|
[ReturnHintsFailure("Updating")]
|
||||||
|
[ReturnHintsFailure("Unknown group")]
|
||||||
|
[ReturnHintsFailure("Invaild group UUID")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[ReturnHintsFailure("Missing group GroupBanAccess power")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[ArgHints("avatar", "URLARG", "the UUID of the avatar or Firstname Lastname")]
|
||||||
|
[ArgHints("state", "URLARG", "true to ban false to unban")]
|
||||||
|
[Route(HttpVerbs.Get, "/GroupBan/{group}/{avatar}/{state}/{token}")]
|
||||||
|
public object GroupBan(string group, string avatar, string state, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group UUID", "GroupBan", new [] { group, avatar, state });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "GroupBan", new [] { group, avatar, state });
|
||||||
|
}
|
||||||
|
Group G = bot.MyGroups[groupuuid];
|
||||||
|
if (G.Powers.HasFlag(GroupPowers.GroupBanAccess) == false)
|
||||||
|
{
|
||||||
|
return Failure("Missing group GroupBanAccess power", "GroupBan", new [] { group, avatar, state });
|
||||||
|
}
|
||||||
|
if (bool.TryParse(state, out bool banstate) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild ban state", "GroupBan", new [] { group, avatar, state });
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if(avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("avatar lookup", "GroupBan", new [] { group, avatar, state });
|
||||||
|
}
|
||||||
|
GroupBanAction action = GroupBanAction.Unban;
|
||||||
|
string statename = "Unban";
|
||||||
|
if (banstate == true)
|
||||||
|
{
|
||||||
|
action = GroupBanAction.Ban;
|
||||||
|
statename = "Ban";
|
||||||
|
}
|
||||||
|
getClient().Groups.RequestBanAction(groupuuid, action, new UUID[] { avataruuid });
|
||||||
|
return BasicReply(statename+" request accepted", "GroupBan", new [] { group, avatar, state });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[About("Eject selected avatar from group")]
|
||||||
|
[ReturnHints("Requested")]
|
||||||
|
[ReturnHintsFailure("Updating")]
|
||||||
|
[ReturnHintsFailure("Unknown group")]
|
||||||
|
[ReturnHintsFailure("Invaild group UUID")]
|
||||||
|
[ReturnHintsFailure("Not in group")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[ReturnHintsFailure("Missing group Eject power")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[ArgHints("avatar", "URLARG", "the UUID of the avatar you wish to check with")]
|
||||||
|
[Route(HttpVerbs.Get, "/GroupEject/{group}/{avatar}/{token}")]
|
||||||
|
public object GroupEject(string group, string avatar, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group UUID", "GroupEject", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "GroupEject", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
Group G = bot.MyGroups[groupuuid];
|
||||||
|
if (G.Powers.HasFlag(GroupPowers.Eject) == false)
|
||||||
|
{
|
||||||
|
return Failure("Missing group Eject power", "GroupEject", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("avatar lookup", "GroupEject", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
getClient().Groups.EjectUser(groupuuid, avataruuid);
|
||||||
|
return BasicReply("Requested", "GroupEject", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Adds the avatar to the Group with the role \n if they are not in the group then it invites them at that role")]
|
||||||
|
[ReturnHints("Roles updated")]
|
||||||
|
[ReturnHints("Invite sent")]
|
||||||
|
[ReturnHintsFailure("Updating")]
|
||||||
|
[ReturnHintsFailure("Unknown group")]
|
||||||
|
[ReturnHintsFailure("Invaild group UUID")]
|
||||||
|
[ReturnHintsFailure("Invaild role UUID")]
|
||||||
|
[ReturnHintsFailure("Not in group")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[ArgHints("avatar", "URLARG", "the UUID of the avatar you wish to check with")]
|
||||||
|
[Route(HttpVerbs.Get, "/GroupAddRole/{group}/{avatar}/{role}/{token}")]
|
||||||
|
public object GroupAddRole(string group, string avatar, string role, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group UUID", "GroupAddRole", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(role, out UUID roleuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild role UUID", "GroupAddRole", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "GroupAddRole", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
if (bot.NeedReloadGroupData(groupuuid) == true)
|
||||||
|
{
|
||||||
|
getClient().Groups.RequestGroupMembers(groupuuid);
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
KeyValuePair<bool, string> reply = waitForReady(true, true, groupuuid);
|
||||||
|
if (reply.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(reply.Value, "GroupAddRole", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
bool status = bot.FastCheckInGroup(groupuuid, avataruuid);
|
||||||
|
if (status == false)
|
||||||
|
{
|
||||||
|
getClient().Groups.Invite(groupuuid, new List<UUID>() { roleuuid }, avataruuid);
|
||||||
|
return BasicReply("Invite sent", "GroupAddRole", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
getClient().Groups.AddToRole(groupuuid, roleuuid, avataruuid);
|
||||||
|
return BasicReply("Roles updated", "GroupAddRole", new [] { group, avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Invites selected avatar to the group with the selected role")]
|
||||||
|
[ReturnHints("Invite sent")]
|
||||||
|
[ReturnHints("Already in group")]
|
||||||
|
[ReturnHintsFailure("Updating")]
|
||||||
|
[ReturnHintsFailure("Unknown group")]
|
||||||
|
[ReturnHintsFailure("Invaild group UUID")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[ReturnHintsFailure("Missing group Invite power")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[ArgHints("avatar", "URLARG", "the UUID of the avatar you wish to check with")]
|
||||||
|
[ArgHints("role", "URLARG", "the UUID of the role to invite them at the word \"everyone\"")]
|
||||||
|
[Route(HttpVerbs.Get, "/GroupInvite/{group}/{avatar}/{role}/{token}")]
|
||||||
|
public object GroupInvite(string group, string avatar, string role, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group UUID", "GroupInvite", new [] { group, avatar, role });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "GroupInvite", new [] { group, avatar, role });
|
||||||
|
}
|
||||||
|
if (bot.NeedReloadGroupData(groupuuid) == true)
|
||||||
|
{
|
||||||
|
getClient().Groups.RequestGroupMembers(groupuuid);
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("avatar lookup", "GroupInvite", new [] { group, avatar, role });
|
||||||
|
}
|
||||||
|
bool status = bot.FastCheckInGroup(groupuuid, avataruuid);
|
||||||
|
if (status == true)
|
||||||
|
{
|
||||||
|
return BasicReply("Already in group", "GroupInvite", new[] { group, avatar, role });
|
||||||
|
}
|
||||||
|
if(role == "everyone")
|
||||||
|
{
|
||||||
|
role = UUID.Zero.ToString();
|
||||||
|
}
|
||||||
|
if(UUID.TryParse(role,out UUID roleuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unable to process role UUID", "GroupInvite", new [] { group, avatar, role });
|
||||||
|
}
|
||||||
|
Group G = bot.MyGroups[groupuuid];
|
||||||
|
if(G.Powers.HasFlag(GroupPowers.Invite) == false)
|
||||||
|
{
|
||||||
|
return Failure("Missing group invite power", "GroupInvite", new [] { group, avatar, role });
|
||||||
|
}
|
||||||
|
getClient().Groups.Invite(groupuuid, new List<UUID>() { roleuuid }, avataruuid);
|
||||||
|
return BasicReply("Invite sent", "GroupInvite", new [] { group, avatar, role });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sends a group notice (No attachments please use GroupnoticeWithAttachment to attach items!)")]
|
||||||
|
[ReturnHints("Sending notice")]
|
||||||
|
[ReturnHintsFailure("Unknown group")]
|
||||||
|
[ReturnHintsFailure("Invaild group UUID")]
|
||||||
|
[ReturnHintsFailure("Title empty")]
|
||||||
|
[ReturnHintsFailure("Message empty")]
|
||||||
|
[ReturnHintsFailure("Missing group Notice power")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[ArgHints("title", "Text", "The title of the group notice")]
|
||||||
|
[ArgHints("message", "Text", "The body of the group notice")]
|
||||||
|
[Route(HttpVerbs.Post, "/Groupnotice/{group}/{token}")]
|
||||||
|
public object Groupnotice(string group, [FormField] string title, [FormField] string message, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group UUID", "Groupnotice", new [] { group, title, message });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "Groupnotice", new [] { group, title, message });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(title) == false)
|
||||||
|
{
|
||||||
|
return Failure("Title empty", "Groupnotice", new [] { group, title, message });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(message) == false)
|
||||||
|
{
|
||||||
|
return Failure("Message empty", "Groupnotice", new [] { group, title, message });
|
||||||
|
}
|
||||||
|
Group G = bot.MyGroups[groupuuid];
|
||||||
|
if (G.Powers.HasFlag(GroupPowers.SendNotices) == false)
|
||||||
|
{
|
||||||
|
return Failure("Missing group notice power", "Groupnotice", new [] { group, title, message });
|
||||||
|
}
|
||||||
|
GroupNotice NewNotice = new GroupNotice();
|
||||||
|
NewNotice.Subject = title;
|
||||||
|
NewNotice.Message = message;
|
||||||
|
NewNotice.OwnerID = getClient().Self.AgentID;
|
||||||
|
getClient().Groups.SendGroupNotice(groupuuid, NewNotice);
|
||||||
|
return BasicReply("Sending notice", "Groupnotice", new [] { group, title, message });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Activates the selected title")]
|
||||||
|
[ReturnHints("Switching title")]
|
||||||
|
[ReturnHintsFailure("Unknown group")]
|
||||||
|
[ReturnHintsFailure("Invaild group UUID")]
|
||||||
|
[ReturnHintsFailure("Invaild role UUID")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[ArgHints("role", "URLARG", "tje UUID of the role")]
|
||||||
|
[Route(HttpVerbs.Get, "/GroupActiveTitle/{group}/{token}")]
|
||||||
|
public object GroupActiveTitle(string group, string role, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group UUID", "GroupActiveTitle", new [] { group, role });
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(role, out UUID roleuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild role UUID", "GroupActiveTitle", new [] { group, role });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "GroupActiveTitle", new [] { group, role });
|
||||||
|
}
|
||||||
|
getClient().Groups.ActivateTitle(groupuuid, roleuuid);
|
||||||
|
return BasicReply("Switching title", "GroupActiveTitle", new [] { group, role });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sets the selected group to the active group")]
|
||||||
|
[ReturnHints("Switching active group")]
|
||||||
|
[ReturnHintsFailure("Unknown group")]
|
||||||
|
[ReturnHintsFailure("Invaild group UUID")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[Route(HttpVerbs.Get, "/GroupActiveGroup/{group}/{token}")]
|
||||||
|
public object GroupActiveGroup(string group, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group UUID", "GroupActiveGroup", new [] { group });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "GroupActiveGroup", new [] { group });
|
||||||
|
}
|
||||||
|
getClient().Groups.ActivateGroup(groupuuid);
|
||||||
|
return BasicReply("Switching active group", "GroupActiveGroup", new [] { group });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sends a group notice with an attachment")]
|
||||||
|
[ReturnHints("Sending notice with attachment")]
|
||||||
|
[ReturnHintsFailure("Unknown group")]
|
||||||
|
[ReturnHintsFailure("Invaild group UUID")]
|
||||||
|
[ReturnHintsFailure("Invaild inventory UUID")]
|
||||||
|
[ReturnHintsFailure("Title empty")]
|
||||||
|
[ReturnHintsFailure("Message empty")]
|
||||||
|
[ReturnHintsFailure("Missing group Notice power")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[ArgHints("title", "Text", "The title of the group notice")]
|
||||||
|
[ArgHints("message", "Text", "The body of the group notice")]
|
||||||
|
[ArgHints("attachment", "URLARG", "the UUID of inventory you wish to attach")]
|
||||||
|
[Route(HttpVerbs.Post, "/Groupnotice/{group}/{attachment}/{token}")]
|
||||||
|
public object GroupnoticeWithAttachment(string group, [FormField] string title, [FormField] string message, string attachment, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group UUID", "GroupnoticeWithAttachment", new [] { group, title, message, attachment });
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(attachment, out UUID inventoryuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild inventory UUID", "GroupnoticeWithAttachment", new [] { group, title, message, attachment });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "GroupnoticeWithAttachment", new [] { group, title, message, attachment });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(title) == false)
|
||||||
|
{
|
||||||
|
return Failure("Title empty", "GroupnoticeWithAttachment", new [] { group, title, message, attachment });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(message) == false)
|
||||||
|
{
|
||||||
|
return Failure("Message empty", "GroupnoticeWithAttachment", new [] { group, title, message, attachment });
|
||||||
|
}
|
||||||
|
Group G = bot.MyGroups[groupuuid];
|
||||||
|
if (G.Powers.HasFlag(GroupPowers.SendNotices) == false)
|
||||||
|
{
|
||||||
|
return Failure("Missing group notice power", "GroupnoticeWithAttachment", new [] { group, title, message, attachment });
|
||||||
|
}
|
||||||
|
GroupNotice NewNotice = new GroupNotice();
|
||||||
|
NewNotice.Subject = title;
|
||||||
|
NewNotice.Message = message;
|
||||||
|
NewNotice.OwnerID = getClient().Self.AgentID;
|
||||||
|
NewNotice.AttachmentID = inventoryuuid;
|
||||||
|
getClient().Groups.SendGroupNotice(groupuuid, NewNotice);
|
||||||
|
return BasicReply("Sending notice with attachment", "GroupnoticeWithAttachment", new [] { group, title, message, attachment });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("fetchs a list of all groups known to the bot")]
|
||||||
|
[ReturnHints("array UUID=name")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetGroupList/{token}")]
|
||||||
|
public object GetGroupList(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
Dictionary<string, string> grouppackage = new Dictionary<string, string>();
|
||||||
|
foreach (KeyValuePair<UUID, Group> entry in bot.MyGroups)
|
||||||
|
{
|
||||||
|
grouppackage.Add(entry.Value.ID.ToString(), entry.Value.Name);
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(grouppackage), "GetGroupList");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Requests the roles for the selected group<br/>Replys with GroupRoleDetails object formated as follows <ul><li>UpdateUnderway (Bool)</li><li>RoleDataAge (Int) [default -1]</li><li>Roles (KeyPair array of UUID=Name)</li></ul><br/>")]
|
||||||
|
[ReturnHints("GroupRoleDetails object")]
|
||||||
|
[ReturnHintsFailure("Group is not currently known")]
|
||||||
|
[ReturnHintsFailure("Invaild group UUID")]
|
||||||
|
[ReturnHintsFailure("Updating")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetGroupRoles/{group}/{token}")]
|
||||||
|
public object GetGroupRoles(string group, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group UUID", "GetGroupRoles", new [] { group });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "GetGroupRoles", new [] { group });
|
||||||
|
}
|
||||||
|
GroupRoleDetails reply = new GroupRoleDetails();
|
||||||
|
reply.UpdateUnderway = false;
|
||||||
|
reply.RoleDataAge = -1;
|
||||||
|
reply.Roles = new Dictionary<string, string>();
|
||||||
|
if (bot.MyGroupRolesStorage.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
reply.UpdateUnderway = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long dif = SecondbotHelpers.UnixTimeNow() - bot.MyGroupRolesStorage[groupuuid].Key;
|
||||||
|
reply.RoleDataAge = dif;
|
||||||
|
if (dif >= 120)
|
||||||
|
{
|
||||||
|
reply.UpdateUnderway = true;
|
||||||
|
}
|
||||||
|
foreach (GroupRole gr in bot.MyGroupRolesStorage[groupuuid].Value)
|
||||||
|
{
|
||||||
|
reply.Roles.Add(gr.ID.ToString(), gr.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reply.UpdateUnderway == true)
|
||||||
|
{
|
||||||
|
getClient().Groups.RequestGroupRoles(groupuuid);
|
||||||
|
if (reply.Roles.Count == 0)
|
||||||
|
{
|
||||||
|
return Failure("Updating", "GetGroupRoles", new [] { group });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(reply), "GetGroupRoles", new [] { group });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("fetchs a list of all groups with unread messages")]
|
||||||
|
[ReturnHints("array UUID")]
|
||||||
|
[Route(HttpVerbs.Get, "/GroupchatListAllUnreadGroups/{token}")]
|
||||||
|
public object GroupchatListAllUnreadGroups(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(bot.UnreadGroupchatGroups()), "GroupchatListAllUnreadGroups");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("fetchs a list of all groups with unread messages")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ReturnHintsFailure("Unknown group")]
|
||||||
|
[ReturnHintsFailure("group value is invaild")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[Route(HttpVerbs.Get, "/GroupchatGroupHasUnread/{group}/{token}")]
|
||||||
|
public object GroupchatGroupHasUnread(string group,string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
UUID groupUUID = UUID.Zero;
|
||||||
|
if(UUID.TryParse(group,out groupUUID) == false)
|
||||||
|
{
|
||||||
|
return Failure("group value is invaild", "GroupchatGroupHasUnread", new [] { group });
|
||||||
|
}
|
||||||
|
if(bot.MyGroups.ContainsKey(groupUUID) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "GroupchatGroupHasUnread", new [] { group });
|
||||||
|
}
|
||||||
|
return BasicReply(bot.GroupHasUnread(groupUUID).ToString(), "GroupchatGroupHasUnread", new [] { group });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("checks if there are any groups with unread messages")]
|
||||||
|
[ReturnHints("True|False")]
|
||||||
|
[Route(HttpVerbs.Get, "/GroupchatAnyUnread/{token}")]
|
||||||
|
public object GroupchatAnyUnread(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
return BasicReply(bot.HasUnreadGroupchats().ToString(), "GroupchatAnyUnread");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Clears all group chat buffers at once")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[Route(HttpVerbs.Get, "/GroupchatClearAll/{token}")]
|
||||||
|
public object GroupchatClearAll(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
bot.ClearAllGroupchat();
|
||||||
|
return BasicReply("ok", "GroupchatClearAll");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("fetchs the groupchat history")]
|
||||||
|
[ReturnHintsFailure("Group UUID invaild")]
|
||||||
|
[ReturnHints("Group Chat")]
|
||||||
|
[ArgHints("group", "URLARG", "the UUID of the group")]
|
||||||
|
[Route(HttpVerbs.Get, "/GroupchatHistory/{group}/{token}")]
|
||||||
|
public object GroupchatHistory(string group, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupUUID) == false)
|
||||||
|
{
|
||||||
|
return Failure("Group UUID invaild", "GroupchatHistory", new [] { group });
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(bot.GetGroupchat(groupUUID)), "GroupchatHistory", new [] { group });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("sends a message to the groupchat")]
|
||||||
|
[ArgHints("group", "URLARG", "UUID of the group")]
|
||||||
|
[ArgHints("message", "Text", "the message to send")]
|
||||||
|
[ReturnHints("Sending")]
|
||||||
|
[ReturnHintsFailure("Group UUID invaild")]
|
||||||
|
[ReturnHintsFailure("Opening groupchat - Please retry later")]
|
||||||
|
[ReturnHintsFailure("Missing group JoinChat power")]
|
||||||
|
[Route(HttpVerbs.Post, "/Groupchat/{group}/{token}")]
|
||||||
|
public object Groupchat(string group, [FormField] string message, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
UUID groupUUID = UUID.Zero;
|
||||||
|
if (UUID.TryParse(group, out groupUUID) == false)
|
||||||
|
{
|
||||||
|
return Failure("group value is invaild", "Groupchat", new [] { group, message });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupUUID) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unknown group", "Groupchat", new [] { group, message });
|
||||||
|
}
|
||||||
|
Group G = bot.MyGroups[groupUUID];
|
||||||
|
if (G.Powers.HasFlag(GroupPowers.JoinChat) == false)
|
||||||
|
{
|
||||||
|
return Failure("Missing group JoinChat power", "Groupchat", new [] { group, message });
|
||||||
|
}
|
||||||
|
if (bot.GetActiveGroupchatSessions.Contains(groupUUID) == false)
|
||||||
|
{
|
||||||
|
getClient().Self.RequestJoinGroupChat(groupUUID);
|
||||||
|
return Failure("Opening groupchat - Please retry later", "Groupchat", new [] { group, message });
|
||||||
|
}
|
||||||
|
getClient().Self.InstantMessageGroup(groupUUID, message);
|
||||||
|
return BasicReply("Sending", "Groupchat", new [] { group, message });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected KeyValuePair<bool, string> waitForReady(bool avatar, bool group, UUID groupuuid)
|
||||||
|
{
|
||||||
|
bool exit = false;
|
||||||
|
int sleeps = 0;
|
||||||
|
string failed_on = "";
|
||||||
|
bool allok = true;
|
||||||
|
while (exit == false)
|
||||||
|
{
|
||||||
|
allok = true;
|
||||||
|
failed_on = "";
|
||||||
|
if (avatar == true)
|
||||||
|
{
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
allok = false;
|
||||||
|
failed_on = "avatar lookup";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((group == true) && (allok == true))
|
||||||
|
{
|
||||||
|
allok = !bot.NeedReloadGroupData(groupuuid);
|
||||||
|
failed_on = "Updating";
|
||||||
|
}
|
||||||
|
if (allok == false)
|
||||||
|
{
|
||||||
|
if (sleeps > 3)
|
||||||
|
{
|
||||||
|
exit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allok == true)
|
||||||
|
{
|
||||||
|
exit = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (exit == false)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
sleeps++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new KeyValuePair<bool, string>(allok, failed_on);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GroupRoleDetails
|
||||||
|
{
|
||||||
|
public bool UpdateUnderway { get; set; }
|
||||||
|
public Dictionary<string,string> Roles { get; set; }
|
||||||
|
public long RoleDataAge = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IsGroupMemberReply
|
||||||
|
{
|
||||||
|
public bool membershipStatus { get; set; }
|
||||||
|
public string AvatarUUID { get; set; }
|
||||||
|
public string GroupUUID { get; set; }
|
||||||
|
public string AvatarnameIfKnown { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
188
SecondBotEvents/Commands/Info.cs
Normal file
188
SecondBotEvents/Commands/Info.cs
Normal file
|
|
@ -0,0 +1,188 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Info : CommandsAPI
|
||||||
|
{
|
||||||
|
public Info(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Lists objects that are sculpty type in the current sim that the bot can see")]
|
||||||
|
[ReturnHints("A json object")]
|
||||||
|
[Route(HttpVerbs.Get, "/ListSculptys/{token}")]
|
||||||
|
public object ListSculptys(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
Dictionary<uint, Primitive> objects_copy = getClient().Network.CurrentSim.ObjectsPrimitives.Copy();
|
||||||
|
|
||||||
|
Dictionary<uint, uint> mapLocalID = new Dictionary<uint, uint>();
|
||||||
|
Dictionary<uint, Primitive> sculpts = new Dictionary<uint, Primitive>();
|
||||||
|
foreach (KeyValuePair<uint, Primitive> Obj in objects_copy)
|
||||||
|
{
|
||||||
|
mapLocalID.Add(Obj.Value.LocalID, Obj.Key);
|
||||||
|
if (PrimType.Sculpt.Equals(Obj.Value.Type) == true)
|
||||||
|
{
|
||||||
|
sculpts.Add(Obj.Key, Obj.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<SculptysInfo> reply = new List<SculptysInfo>();
|
||||||
|
foreach (KeyValuePair<uint, Primitive> Obj in sculpts)
|
||||||
|
{
|
||||||
|
Vector3 pos = Obj.Value.Position;
|
||||||
|
string name = "?";
|
||||||
|
if (Obj.Value.NameValues != null)
|
||||||
|
{
|
||||||
|
name = Obj.Value.NameValues[0].Value.ToString();
|
||||||
|
}
|
||||||
|
UUID key = Obj.Value.ID;
|
||||||
|
UUID owner = Obj.Value.OwnerID;
|
||||||
|
bool asLink = false;
|
||||||
|
if (Obj.Value.ParentID > 0)
|
||||||
|
{
|
||||||
|
if(mapLocalID.ContainsKey(Obj.Value.ParentID) == true)
|
||||||
|
{
|
||||||
|
Primitive wip = objects_copy[mapLocalID[Obj.Value.ParentID]];
|
||||||
|
pos = wip.Position;
|
||||||
|
asLink = true;
|
||||||
|
owner = wip.OwnerID;
|
||||||
|
if (wip.NameValues != null)
|
||||||
|
{
|
||||||
|
name = wip.NameValues[0].Value.ToString();
|
||||||
|
}
|
||||||
|
key = wip.ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SculptysInfo A = new SculptysInfo();
|
||||||
|
A.isLinked = asLink.ToString();
|
||||||
|
A.name = name.ToString();
|
||||||
|
A.owner = owner.ToString();
|
||||||
|
A.uuid = key.ToString();
|
||||||
|
A.pos = pos.ToString();
|
||||||
|
reply.Add(A);
|
||||||
|
}
|
||||||
|
if (reply.Count == 0)
|
||||||
|
{
|
||||||
|
return Failure("No objects found", "ListSculptys");
|
||||||
|
}
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(reply), "ListSculptys",new string[] { });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Fetchs the current bot")]
|
||||||
|
[ReturnHints("The build ID of the bot")]
|
||||||
|
[Route(HttpVerbs.Get, "/Version/{token}")]
|
||||||
|
public object Version(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
return BasicReply(bot.MyVersion, "Version");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Fetchs the name of the bot")]
|
||||||
|
[ReturnHints("Firstname Lastname")]
|
||||||
|
[Route(HttpVerbs.Get, "/Name/{token}")]
|
||||||
|
public object Name(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
return BasicReply(getClient().Self.FirstName + " " + getClient().Self.LastName, "Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Fetchs the current parcels name")]
|
||||||
|
[ReturnHints("Parcelname")]
|
||||||
|
[ReturnHintsFailure("Error parcel not found")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[Route(HttpVerbs.Get, "/ParcelName/{token}")]
|
||||||
|
public object ParcelName(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (getClient().Network.CurrentSim == null)
|
||||||
|
{
|
||||||
|
return Failure("Error not in a sim", "ParcelName");
|
||||||
|
}
|
||||||
|
int localid = getClient().Parcels.GetParcelLocalID(getClient().Network.CurrentSim, getClient().Self.SimPosition);
|
||||||
|
if (getClient().Network.CurrentSim.Parcels.ContainsKey(localid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Error parcel not found", "ParcelName");
|
||||||
|
}
|
||||||
|
return BasicReply(getClient().Network.CurrentSim.Parcels[localid].Name, "ParcelName");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Requests the current unixtime at the bot")]
|
||||||
|
[ReturnHints("Unixtime")]
|
||||||
|
[Route(HttpVerbs.Get, "/UnixTimeNow/{token}")]
|
||||||
|
public object UnixTimeNow(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
return BasicReply(SecondbotHelpers.UnixTimeNow().ToString(), "UnixTimeNow");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Fetchs the current region name")]
|
||||||
|
[ReturnHints("Regionname")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[Route(HttpVerbs.Get, "/SimName/{token}")]
|
||||||
|
public object SimName(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (getClient().Network.CurrentSim == null)
|
||||||
|
{
|
||||||
|
return Failure("Error not in a sim", "SimName");
|
||||||
|
}
|
||||||
|
return BasicReply(getClient().Network.CurrentSim.Name, "SimName");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Fetchs the current location of the bot")]
|
||||||
|
[ReturnHints("array of X,Y,Z values")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetPosition/{token}")]
|
||||||
|
public object GetPosition(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (getClient().Network.CurrentSim == null)
|
||||||
|
{
|
||||||
|
return Failure("Error not in a sim", "GetPosition");
|
||||||
|
}
|
||||||
|
Dictionary<string, int> pos = new Dictionary<string, int>();
|
||||||
|
pos.Add("x", (int)Math.Round(getClient().Self.SimPosition.X));
|
||||||
|
pos.Add("y", (int)Math.Round(getClient().Self.SimPosition.Y));
|
||||||
|
pos.Add("z", (int)Math.Round(getClient().Self.SimPosition.Z));
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(pos), "GetPosition");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SculptysInfo
|
||||||
|
{
|
||||||
|
public string name = "";
|
||||||
|
public string isLinked = "False";
|
||||||
|
public string owner = "?";
|
||||||
|
public string uuid = "?";
|
||||||
|
public string pos = "<0,0,0>";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
516
SecondBotEvents/Commands/Inventory.cs
Normal file
516
SecondBotEvents/Commands/Inventory.cs
Normal file
|
|
@ -0,0 +1,516 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.Assets;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Inventory : CommandsAPI
|
||||||
|
{
|
||||||
|
public Inventory(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Attachs an event for inventory changes")]
|
||||||
|
[ReturnHints("cleared")]
|
||||||
|
[ReturnHints("No action")]
|
||||||
|
[ReturnHints("Event added")]
|
||||||
|
[ArgHints("inventoryType", "URLARG", "Types: texture,sound,callcard,landmark,clothing,object,notecard,lsltext,lslbyte,animatn,gesture,mesh")]
|
||||||
|
[ArgHints("outputTarget", "text", "HTTP url, channel, avatar UUID or clear to remove all events for the selected type")]
|
||||||
|
[Route(HttpVerbs.Post, "/SetInventoryUpdate/{inventoryType}/{token}")]
|
||||||
|
public object SetInventoryUpdate(string inventoryType, [FormField] string outputTarget, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
return BasicReply(bot.addInventoryUpdateEvent(inventoryType, outputTarget), "SetInventoryUpdate");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Uploads a new sound file to inventory")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ArgHints("sourcePath", "Text", "accepts a file path to a wave PCM file @ 44100")]
|
||||||
|
[ArgHints("inventoryName", "URLARG", "the name in secondlife")]
|
||||||
|
[Route(HttpVerbs.Post, "/UploadMediaWave/{inventoryName}/{token}")]
|
||||||
|
public object UploadMediaWave([FormField] string sourcePath, string inventoryName, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
byte[] audioData = File.ReadAllBytes(sourcePath);
|
||||||
|
InventoryFolder AA = getClient().Inventory.Store.RootFolder;
|
||||||
|
List<InventoryBase> T = getClient().Inventory.Store.GetContents(AA);
|
||||||
|
AA = null;
|
||||||
|
foreach (InventoryBase R in T)
|
||||||
|
{
|
||||||
|
if (R.Name == "Sounds")
|
||||||
|
{
|
||||||
|
AA = (InventoryFolder)R;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AssetSound S = new AssetSound();
|
||||||
|
S.AssetData = audioData;
|
||||||
|
S.Encode();
|
||||||
|
|
||||||
|
getClient().Inventory.RequestCreateItemFromAsset(S.AssetData, inventoryName, "", AssetType.Sound, InventoryType.Sound, AA.UUID, null);
|
||||||
|
return BasicReply("ok", "UploadMediaWave");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("rezs the item at the bots current location")]
|
||||||
|
[ReturnHints("UUID of rezzed item")]
|
||||||
|
[ReturnHints("Invaild item UUID")]
|
||||||
|
[ReturnHints("Unable to find item")]
|
||||||
|
[ArgHints("item", "URLARG", "UUID of item to rez")]
|
||||||
|
[Route(HttpVerbs.Get, "/RezObject/{item}/{token}")]
|
||||||
|
public object RezObject(string item, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(item, out UUID targetitem) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild item UUID: "+ item, "RezObject", new [] { item });
|
||||||
|
}
|
||||||
|
InventoryItem itm = getClient().Inventory.FetchItem(targetitem, getClient().Self.AgentID, (5 * 1000));
|
||||||
|
if (itm == null)
|
||||||
|
{
|
||||||
|
return Failure("Unable to find item: " + item, "RezObject", new [] { item });
|
||||||
|
}
|
||||||
|
UUID rezedobject = getClient().Inventory.RequestRezFromInventory(getClient().Network.CurrentSim, getClient().Self.SimRotation, getClient().Self.RelativePosition, itm);
|
||||||
|
return BasicReply(rezedobject.ToString(), "RezObject", new [] { item });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("renames a folder or inventory item")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHints("invaild item uuid")]
|
||||||
|
[ReturnHints("Item name is to short")]
|
||||||
|
[ReturnHints("Unable to find inventory item")]
|
||||||
|
[ArgHints("item", "URLARG", "UUID of item/folder to name")]
|
||||||
|
[ArgHints("newname", "Text", "What we are changing it to")]
|
||||||
|
[Route(HttpVerbs.Post, "/RenameInventory/{item}/{token}")]
|
||||||
|
public object RenameInventory(string item, [FormField] string newname, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(item, out UUID target) == false)
|
||||||
|
{
|
||||||
|
return Failure("invaild item uuid", "RenameInventory", new [] { item, newname });
|
||||||
|
}
|
||||||
|
if (newname.Length < 3)
|
||||||
|
{
|
||||||
|
return Failure("Item name is to short", "RenameInventory", new [] { item, newname });
|
||||||
|
}
|
||||||
|
InventoryItem realitem = HelperInventory.getItemByInventoryUUID(bot, target);
|
||||||
|
if (realitem == null)
|
||||||
|
{
|
||||||
|
return Failure("Unable to find inventory item", "RenameInventory", new [] { item, newname });
|
||||||
|
}
|
||||||
|
realitem.Name = newname;
|
||||||
|
getClient().Inventory.RequestUpdateItem(realitem);
|
||||||
|
return BasicReply("Ok", "RenameInventory", new [] { item, newname });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Attempts to Remove the given inventory item")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHints("invaild item uuid")]
|
||||||
|
[ArgHints("item", "URLARG", "UUID of item")]
|
||||||
|
[Route(HttpVerbs.Get, "/DeleteInventoryItem/{item}/{token}")]
|
||||||
|
public object DeleteInventoryItem(string item, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(item, out UUID target) == false)
|
||||||
|
{
|
||||||
|
return Failure("invaild item uuid", "DeleteInventoryItem", new [] { item });
|
||||||
|
}
|
||||||
|
getClient().Inventory.Remove(new List<UUID>() { target }, new List<UUID>());
|
||||||
|
return BasicReply("Ok", "DeleteInventoryItem", new [] { item });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Attempts to Remove the given inventory folder")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHints("invaild folder uuid")]
|
||||||
|
[ArgHints("folder", "URLARG", "UUID of folder")]
|
||||||
|
[Route(HttpVerbs.Get, "/DeleteInventoryFolder/{folder}/{token}")]
|
||||||
|
public object DeleteInventoryFolder(string folder, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(folder, out UUID target) == false)
|
||||||
|
{
|
||||||
|
return Failure("invaild folder uuid", "DeleteInventoryFolder", new [] { folder });
|
||||||
|
}
|
||||||
|
getClient().Inventory.Remove(new List<UUID>(), new List<UUID>() { target });
|
||||||
|
return BasicReply("Ok", "DeleteInventoryFolder", new [] { folder });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Attempts to attach the given inventory item")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHints("invaild item uuid")]
|
||||||
|
[ArgHints("item", "URLARG", "UUID of item")]
|
||||||
|
[Route(HttpVerbs.Get, "/Attach/{item}/{token}")]
|
||||||
|
public object Attach(string item, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(item,out UUID itemuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("invaild item uuid", "Attach", new [] { item });
|
||||||
|
}
|
||||||
|
InventoryItem realitem = HelperInventory.getItemByInventoryUUID(bot, itemuuid);
|
||||||
|
getClient().Appearance.AddAttachments(new List<InventoryItem>() { realitem }, false, false);
|
||||||
|
return BasicReply("Ok", "Attach", new [] { item });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Attempts to Remove the given inventory folder")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHints("invaild item uuid")]
|
||||||
|
[ArgHints("item", "URLARG", "UUID of item")]
|
||||||
|
[Route(HttpVerbs.Get, "/Detach/{item}/{token}")]
|
||||||
|
public object Detach(string item, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(item, out UUID itemuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("invaild item uuid", "Detach", new [] { item });
|
||||||
|
}
|
||||||
|
InventoryItem realitem = HelperInventory.getItemByInventoryUUID(bot, itemuuid);
|
||||||
|
getClient().Appearance.RemoveFromOutfit(realitem);
|
||||||
|
return BasicReply("Ok", "Detach", new [] { item });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Replaces the current avatar outfit with the Clothing/[NAME] folder<br/>Please note: This does not use the outfits folder!<br/>Please do not use links in the folder!")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHints("Named folder value is empty")]
|
||||||
|
[ReturnHints("Cant find Clothing folder")]
|
||||||
|
[ReturnHints("Cant find target folder")]
|
||||||
|
[ReturnHints("target folder is empty or so full I cant get it in 5 secs...")]
|
||||||
|
[ArgHints("name", "URLARG", "Name of the folder")]
|
||||||
|
[Route(HttpVerbs.Get, "/Outfit/{name}/{token}")]
|
||||||
|
public object Outfit(string name, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(name) == false)
|
||||||
|
{
|
||||||
|
return Failure("Named folder value is empty", "Outfit", new [] { name });
|
||||||
|
}
|
||||||
|
// uses the Clothing folder
|
||||||
|
// must be a full outfit (shapes/eyes ect)
|
||||||
|
InventoryFolder AA = getClient().Inventory.Store.RootFolder;
|
||||||
|
List<InventoryBase> T = getClient().Inventory.Store.GetContents(AA);
|
||||||
|
AA = null;
|
||||||
|
foreach (InventoryBase R in T)
|
||||||
|
{
|
||||||
|
if (R.Name == "Clothing")
|
||||||
|
{
|
||||||
|
AA = (InventoryFolder)R;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (AA == null)
|
||||||
|
{
|
||||||
|
return Failure("Cant find Clothing folder", "Outfit", new [] { name });
|
||||||
|
}
|
||||||
|
T = getClient().Inventory.Store.GetContents(AA);
|
||||||
|
AA = null;
|
||||||
|
foreach (InventoryBase R in T)
|
||||||
|
{
|
||||||
|
if (R.Name == name)
|
||||||
|
{
|
||||||
|
AA = (InventoryFolder)R;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (AA == null)
|
||||||
|
{
|
||||||
|
return Failure("Cant find target folder", "Outfit", new [] { name });
|
||||||
|
}
|
||||||
|
List<InventoryBase> contents = getClient().Inventory.FolderContents(AA.UUID, getClient().Self.AgentID, true, true, InventorySortOrder.ByName, 5 * 1000);
|
||||||
|
List<InventoryItem> wareables = new List<InventoryItem>();
|
||||||
|
if (contents == null)
|
||||||
|
{
|
||||||
|
return Failure("target folder is empty or so full I cant get it in 5 secs...", "Outfit", new [] { name });
|
||||||
|
}
|
||||||
|
foreach (InventoryBase item in contents)
|
||||||
|
{
|
||||||
|
if ((item is InventoryWearable) || (item is InventoryObject))
|
||||||
|
{
|
||||||
|
wareables.Add((InventoryItem)item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getClient().Appearance.ReplaceOutfit(wareables, false);
|
||||||
|
return BasicReply("ok", "Outfit", new [] { name });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[About("Searchs the notecards folder for notecards, any older than 31 days are deleted.<br/>Depending on the number of notecards this might require multiple calls!")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHints("Unable to find notecard folder")]
|
||||||
|
[Route(HttpVerbs.Get, "/InventoryPurgeNotecards/{token}")]
|
||||||
|
public object InventoryPurgeNotecards(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
List<InventoryBase> T = getClient().Inventory.Store.GetContents(getClient().Inventory.Store.RootFolder);
|
||||||
|
InventoryBase NotecardFolder = null;
|
||||||
|
foreach (InventoryBase R in T)
|
||||||
|
{
|
||||||
|
if (R.Name == "Notecards")
|
||||||
|
{
|
||||||
|
NotecardFolder = R;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NotecardFolder != null)
|
||||||
|
{
|
||||||
|
return Failure("Unable to find notecard folder", "InventoryPurgeNotecards");
|
||||||
|
}
|
||||||
|
List<UUID> purge_notecards = new List<UUID>();
|
||||||
|
List<InventoryBase> contents = getClient().Inventory.FolderContents(NotecardFolder.UUID, getClient().Self.AgentID, true, true, InventorySortOrder.ByDate, 40 * 1000);
|
||||||
|
foreach (InventoryBase C in contents)
|
||||||
|
{
|
||||||
|
InventoryItem A = (InventoryItem)C;
|
||||||
|
if (A.AssetType == AssetType.Notecard)
|
||||||
|
{
|
||||||
|
TimeSpan Dif = DateTime.Now - A.CreationDate;
|
||||||
|
if (Dif.Days >= 31)
|
||||||
|
{
|
||||||
|
purge_notecards.Add(C.UUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (purge_notecards.Count() > 0)
|
||||||
|
{
|
||||||
|
getClient().Inventory.Remove(purge_notecards, new List<UUID>());
|
||||||
|
}
|
||||||
|
return BasicReply("Ok", "InventoryPurgeNotecards");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("converts a inventory uuid to a realworld uuid<br/>Needed for texture preview")]
|
||||||
|
[ReturnHints("Asset UUID or UUID zero")]
|
||||||
|
[ReturnHints("Invaild item uuid")]
|
||||||
|
[ArgHints("item", "URLARG", "inventory level UUID of item")]
|
||||||
|
[Route(HttpVerbs.Get, "/getRealUUID/{item}/{token}")]
|
||||||
|
public object getRealUUID(string item, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(item, out UUID itemUUID) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild item uuid", "getRealUUID", new [] { item });
|
||||||
|
}
|
||||||
|
UUID reply = HelperInventory.GetAssetUUID(bot, itemUUID);
|
||||||
|
return BasicReply(reply.ToString(), "getRealUUID", new [] { item });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("sends a item to an avatar")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHints("Failed")]
|
||||||
|
[ReturnHints("Invaild avatar uuid")]
|
||||||
|
[ReturnHints("Invaild item uuid")]
|
||||||
|
[ReturnHints("Unable to find item")]
|
||||||
|
[ArgHints("item", "URLARG", "UUID of item")]
|
||||||
|
[ArgHints("avatar", "URLARG", "a UUID or Firstname Lastname")]
|
||||||
|
[Route(HttpVerbs.Get, "/SendItem/{item}/{avatar}/{token}")]
|
||||||
|
public object SendItem(string item, string avatar, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if(avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar uuid", "SendItem", new [] { item, avatar });
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(item, out UUID targetitem) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild item uuid", "SendItem", new [] { item, avatar });
|
||||||
|
}
|
||||||
|
InventoryItem itm = getClient().Inventory.FetchItem(targetitem, getClient().Self.AgentID, (3 * 1000));
|
||||||
|
if (itm == null)
|
||||||
|
{
|
||||||
|
return Failure("Unable to find item", "SendItem", new [] { item, avatar });
|
||||||
|
}
|
||||||
|
getClient().Inventory.GiveItem(itm.UUID, itm.Name, itm.AssetType, avataruuid, false);
|
||||||
|
return BasicReply("ok", "SendItem", new [] { item, avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sends a folder to an avatar")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHints("Failed")]
|
||||||
|
[ReturnHints("Invaild avatar uuid")]
|
||||||
|
[ReturnHints("Invaild folter uuid")]
|
||||||
|
[ReturnHints("Unable to find folder")]
|
||||||
|
[ArgHints("item", "URLARG", "UUID of item")]
|
||||||
|
[ArgHints("avatar", "URLARG", "a UUID or Firstname Lastname")]
|
||||||
|
[Route(HttpVerbs.Get, "/SendFolder/{folder}/{avatar}/{token}")]
|
||||||
|
public object SendFolder(string folder, string avatar, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar uuid", "SendFolder", new [] { folder, avatar });
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(folder, out UUID targetfolder) == true)
|
||||||
|
{
|
||||||
|
return Failure("Invaild folder uuid", "SendFolder", new [] { folder, avatar });
|
||||||
|
}
|
||||||
|
InventoryBase FindFolderHelper = HelperInventory.FindFolder(bot, getClient().Inventory.Store.RootFolder, targetfolder);
|
||||||
|
if (FindFolderHelper == null)
|
||||||
|
{
|
||||||
|
return Failure("Unable to find folder", "SendFolder", new [] { folder, avatar });
|
||||||
|
}
|
||||||
|
getClient().Inventory.GiveFolder(FindFolderHelper.UUID, FindFolderHelper.Name, avataruuid, false);
|
||||||
|
return BasicReply("ok", "SendFolder", new [] { folder, avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[About("Transfers a item [ARG 2] to a objects inventory [ARG 1] (And if set with the script running state [ARG 3])")]
|
||||||
|
[ReturnHints("Transfering running script")]
|
||||||
|
[ReturnHints("Transfering inventory")]
|
||||||
|
[ReturnHints("Invaild item uuid")]
|
||||||
|
[ReturnHints("Invaild object uuid")]
|
||||||
|
[ReturnHints("Unable to find inventory")]
|
||||||
|
[ReturnHints("Unable to find object")]
|
||||||
|
[ReturnHints("Invaild running")]
|
||||||
|
[ArgHints("item", "URLARG", "UUID of item")]
|
||||||
|
[ArgHints("object", "URLARG", "the uuid of the object")]
|
||||||
|
[ArgHints("running", "URLARG", "true if you wish the transfered script to be running otherwise false")]
|
||||||
|
|
||||||
|
[Route(HttpVerbs.Get, "/TransferInventoryToObject/{item}/{objectuuid}/{running}/{token}")]
|
||||||
|
public object TransferInventoryToObject(string item, string objectuuid, string running, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(item, out UUID itemuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild item uuid", "TransferInventoryToObject", new [] { item, objectuuid, running });
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(objectuuid, out UUID objectUUID) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild object uuid", "TransferInventoryToObject", new [] { item, objectuuid, running });
|
||||||
|
}
|
||||||
|
if (bool.TryParse(running, out bool runscript) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild running", "TransferInventoryToObject", new [] { item, objectuuid, running });
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryItem itm = getClient().Inventory.FetchItem(itemuuid, getClient().Self.AgentID, (3 * 1000));
|
||||||
|
if (itm == null)
|
||||||
|
{
|
||||||
|
return Failure("Unable to find inventory", "TransferInventoryToObject", new [] { item, objectuuid, running });
|
||||||
|
}
|
||||||
|
Dictionary<uint, Primitive> objects_copy = getClient().Network.CurrentSim.ObjectsPrimitives.Copy();
|
||||||
|
KeyValuePair<uint, Primitive> RealObject = new KeyValuePair<uint, Primitive>(0,null);
|
||||||
|
foreach (KeyValuePair<uint, Primitive> Obj in objects_copy)
|
||||||
|
{
|
||||||
|
if (Obj.Value.ID == objectUUID)
|
||||||
|
{
|
||||||
|
RealObject = Obj;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (RealObject.Value == null)
|
||||||
|
{
|
||||||
|
return Failure("Unable to find object", "TransferInventoryToObject", new [] { item, objectuuid, running });
|
||||||
|
}
|
||||||
|
bool scriptState = runscript;
|
||||||
|
if (itm.AssetType != AssetType.LSLText)
|
||||||
|
{
|
||||||
|
scriptState = false;
|
||||||
|
}
|
||||||
|
if (itm.AssetType == AssetType.LSLText)
|
||||||
|
{
|
||||||
|
getClient().Inventory.CopyScriptToTask(RealObject.Key, itm, scriptState);
|
||||||
|
return BasicReply("Transfering script [state: "+scriptState.ToString()+"]", "TransferInventoryToObject", new [] { item, objectuuid, running });
|
||||||
|
}
|
||||||
|
getClient().Inventory.UpdateTaskInventory(RealObject.Key, itm);
|
||||||
|
return BasicReply("Transfering inventory", "TransferInventoryToObject", new [] { item, objectuuid, running });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Requests the inventory folder layout as a json object InventoryMapFolder<br/>Formated as follows<br/>InventoryMapItem<br/><ul><li>id: UUID</li><li>name: String</li><li>subfolders: InventoryMapFolder[]</li></ul>")]
|
||||||
|
[ReturnHints("array of InventoryMapFolder")]
|
||||||
|
[ReturnHints("Error")]
|
||||||
|
[Route(HttpVerbs.Get, "/InventoryFolders/{token}")]
|
||||||
|
public object InventoryFolders(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
string reply = HelperInventory.MapFolderJson(bot);
|
||||||
|
if (reply != null) return BasicReply(reply, "InventoryFolders");
|
||||||
|
return Failure("Error", "InventoryFolders");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Requests folders limited to selected folder")]
|
||||||
|
[ArgHints("targetfolder", "URLARG", "the UUID of the folder or root")]
|
||||||
|
[ReturnHints("single InventoryMapFolder")]
|
||||||
|
[ReturnHints("Error")]
|
||||||
|
[Route(HttpVerbs.Get, "/InventoryFoldersLimited/{targetfolder}/{token}")]
|
||||||
|
public object InventoryFoldersLimited(string targetfolder,string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
string reply = HelperInventory.MapFolderJson(bot, targetfolder,false);
|
||||||
|
if (reply != null) return BasicReply(reply, "InventoryFoldersLimited");
|
||||||
|
return Failure("Error", "InventoryFoldersLimited");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Requests the contents of a folder as an array of InventoryMapItem<br/>Formated as follows<br/>InventoryMapItem<br/><ul><li>id: UUID</li><li>name: String</li><li>typename: String</li></ul>")]
|
||||||
|
[ReturnHints("array of InventoryMapItem")]
|
||||||
|
[ReturnHints("Invaild folder UUID")]
|
||||||
|
[ArgHints("folderUUID", "URLARG", "the folder to fetch (Found via: inventory/folders)")]
|
||||||
|
[Route(HttpVerbs.Get, "/InventoryContents/{folderUUID}/{token}")]
|
||||||
|
public object InventoryContents(string folderUUID, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(folderUUID, out UUID folder) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild folder UUID", "InventoryContents", new [] { folderUUID });
|
||||||
|
}
|
||||||
|
return BasicReply(HelperInventory.MapFolderInventoryJson(bot, folder), "InventoryContents", new [] { folderUUID });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
313
SecondBotEvents/Commands/Movement.cs
Normal file
313
SecondBotEvents/Commands/Movement.cs
Normal file
|
|
@ -0,0 +1,313 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Movement : CommandsAPI
|
||||||
|
{
|
||||||
|
public Movement(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("uses the AutoPilot to move to a location")]
|
||||||
|
[ReturnHints("Error Unable to AutoPilot to location")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Convert to vector has failed")]
|
||||||
|
[ReturnHintsFailure("? value out of range 0-?")]
|
||||||
|
[ArgHints("x", "URLARG", "X location to AutoPilot to")]
|
||||||
|
[ArgHints("y", "URLARG", "y location to AutoPilot to")]
|
||||||
|
[ArgHints("z", "URLARG", "z location to AutoPilot to")]
|
||||||
|
[Route(HttpVerbs.Get, "/AutoPilot/{x}/{y}/{z}/{token}")]
|
||||||
|
public object AutoPilot(string x, string y, string z, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (Vector3.TryParse("<" + x + "," + y + "," + z + ">", out Vector3 pos) == false)
|
||||||
|
{
|
||||||
|
return Failure("Convert to vector has failed", "AutoPilot", new [] { x, y, z });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.inrange(pos.X, 0, 255) == false)
|
||||||
|
{
|
||||||
|
return Failure("x value out of range 0-255", "AutoPilot", new [] { x, y, z });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.inrange(pos.Y, 0, 255) == false)
|
||||||
|
{
|
||||||
|
return Failure("y value out of range 0-255", "AutoPilot", new [] { x, y, z });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.inrange(pos.Z, 0, 5000) == false)
|
||||||
|
{
|
||||||
|
return Failure("z value out of range 0-5000", "AutoPilot", new [] { x, y, z });
|
||||||
|
}
|
||||||
|
getClient().Self.AutoPilotCancel();
|
||||||
|
getClient().Self.Movement.TurnToward(pos, true);
|
||||||
|
Thread.Sleep(500);
|
||||||
|
uint Globalx, Globaly;
|
||||||
|
Utils.LongToUInts(getClient().Network.CurrentSim.Handle, out Globalx, out Globaly);
|
||||||
|
getClient().Self.AutoPilot((ulong)(Globalx + pos.X), (ulong)(Globaly + pos.Y), pos.Z);
|
||||||
|
return BasicReply("ok", "AutoPilot", new [] { x, y, z });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Attempt to teleport to a new region")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[Route(HttpVerbs.Get, "/AutoPilotStop/{token}")]
|
||||||
|
public object AutoPilotStop(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
getClient().Self.AutoPilotCancel();
|
||||||
|
return BasicReply("ok", "AutoPilotStop");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Make the bot request the target avatar teleport to the bot")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Invaild avatar UUID")]
|
||||||
|
[ArgHints("avatar", "URLARG", "Avatar UUID or Firstname Lastname")]
|
||||||
|
[Route(HttpVerbs.Get, "/SendTeleportLure/{avatar}/{token}")]
|
||||||
|
public object SendTeleportLure(string avatar,string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if(avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar UUID", "SendTeleportLure", new [] { avatar });
|
||||||
|
}
|
||||||
|
getClient().Self.SendTeleportLure(avataruuid);
|
||||||
|
return BasicReply("ok", "SendTeleportLure", new [] { avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sends a teleport request (Move the bot to the avatar)")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Invaild avatar UUID")]
|
||||||
|
[ArgHints("avatar", "URLARG", "Avatar UUID or Firstname Lastname")]
|
||||||
|
[Route(HttpVerbs.Get, "/RequestTeleport/{avatar}/{token}")]
|
||||||
|
public object RequestTeleport(string avatar, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar UUID", "RequestTeleport", new [] { avatar });
|
||||||
|
}
|
||||||
|
bot.Add_action_from("teleport", avataruuid, bot.FindAvatarKey2Name(avataruuid));
|
||||||
|
getClient().Self.SendTeleportLureRequest(avataruuid, "I would like to teleport to you");
|
||||||
|
return BasicReply("ok", "RequestTeleport", new [] { avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Makes the bot fly (or not)")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Invaild mode")]
|
||||||
|
[ArgHints("mode", "URLARG", "true: Start flying, false: stop flying (super fun at height)")]
|
||||||
|
[Route(HttpVerbs.Get, "/Fly/{mode}/{token}")]
|
||||||
|
public object Fly(string mode, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bool.TryParse(mode, out bool flymode) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild mode", "Fly", new [] { mode });
|
||||||
|
}
|
||||||
|
getClient().Self.Movement.Fly = flymode;
|
||||||
|
getClient().Self.Movement.SendUpdate();
|
||||||
|
return BasicReply("ok", "Fly", new [] { mode });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[About("Rotates the bot to face a vector from its current location")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ReturnHintsFailure("Invaild vector")]
|
||||||
|
[ReturnHintsFailure("Vector ? value is out of range 0-?")]
|
||||||
|
[ArgHints("vector", "Text", "a vector to face eg <123,45,44>")]
|
||||||
|
[Route(HttpVerbs.Post, "/RotateToFaceVector/{token}")]
|
||||||
|
public object RotateToFaceVector([FormField] string vector, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (Vector3.TryParse(vector, out Vector3 pos) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild vector", "RotateToFaceVector", new [] { vector });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.inrange(pos.X, 0, 255) == false)
|
||||||
|
{
|
||||||
|
return Failure("Vector x value is out of range 0-255", "RotateToFaceVector", new [] { vector });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.inrange(pos.Y, 0, 255) == false)
|
||||||
|
{
|
||||||
|
return Failure("Vector y value is out of range 0-255", "RotateToFaceVector", new [] { vector });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.inrange(pos.Z, 0, 5000) == false)
|
||||||
|
{
|
||||||
|
return Failure("Vector z value is out of range 0-5000", "RotateToFaceVector", new [] { vector });
|
||||||
|
}
|
||||||
|
return BasicReply(getClient().Self.Movement.TurnToward(pos, true).ToString(), "RotateToFaceVector", new [] { vector });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Rotates the bot to face a avatar")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ReturnHintsFailure("Invaild avatar UUID")]
|
||||||
|
[ReturnHintsFailure("Unable to see avatar")]
|
||||||
|
[ArgHints("avatar", "URLARG", "An avatar UUID or Firstname Lastname")]
|
||||||
|
[Route(HttpVerbs.Post, "/RotateToFace/{avatar}/{token}")]
|
||||||
|
public object RotateToFace(string avatar, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if(avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar UUID", "RotateToFace", new [] { avatar });
|
||||||
|
}
|
||||||
|
if (getClient().Network.CurrentSim.AvatarPositions.ContainsKey(avataruuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unable to see avatar", "RotateToFace", new [] { avatar });
|
||||||
|
}
|
||||||
|
return BasicReply(getClient().Self.Movement.TurnToward(getClient().Network.CurrentSim.AvatarPositions[avataruuid], true).ToString(), "RotateToFace", new [] { avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("Rotates the avatar to face a rotation from north in Degrees")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Unable to process rotation")]
|
||||||
|
[ArgHints("deg", "URLARG", "0 to 360")]
|
||||||
|
[Route(HttpVerbs.Post, "/RotateTo/{deg}/{token}")]
|
||||||
|
public object RotateTo(string deg, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (float.TryParse(deg, out float target_yaw) == true)
|
||||||
|
{
|
||||||
|
return Failure("Unable to process rotation", "RotateTo", new [] { deg });
|
||||||
|
}
|
||||||
|
float yaw = target_yaw;
|
||||||
|
getClient().Self.Movement.BodyRotation.GetEulerAngles(out float roll, out float pitch, out _);
|
||||||
|
roll *= 57.2958f;
|
||||||
|
pitch *= 57.2958f;
|
||||||
|
yaw *= 57.2958f;
|
||||||
|
float rollOver2 = roll * 0.5f;
|
||||||
|
float sinRollOver2 = (float)Math.Sin((double)rollOver2);
|
||||||
|
float cosRollOver2 = (float)Math.Cos((double)rollOver2);
|
||||||
|
float pitchOver2 = pitch * 0.5f;
|
||||||
|
float sinPitchOver2 = (float)Math.Sin((double)pitchOver2);
|
||||||
|
float cosPitchOver2 = (float)Math.Cos((double)pitchOver2);
|
||||||
|
float yawOver2 = yaw * 0.5f;
|
||||||
|
float sinYawOver2 = (float)Math.Sin((double)yawOver2);
|
||||||
|
float cosYawOver2 = (float)Math.Cos((double)yawOver2);
|
||||||
|
Quaternion result;
|
||||||
|
result.W = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2;
|
||||||
|
result.X = cosYawOver2 * sinPitchOver2 * cosRollOver2 + sinYawOver2 * cosPitchOver2 * sinRollOver2;
|
||||||
|
result.Y = sinYawOver2 * cosPitchOver2 * cosRollOver2 - cosYawOver2 * sinPitchOver2 * sinRollOver2;
|
||||||
|
result.Z = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2;
|
||||||
|
getClient().Self.Movement.BodyRotation = result;
|
||||||
|
getClient().Self.Movement.SendUpdate();
|
||||||
|
return BasicReply("ok", "RotateTo", new [] { deg });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[About("Attempt to teleport to a new region")]
|
||||||
|
[ReturnHintsFailure("Error Unable to Teleport to location")]
|
||||||
|
[ReturnHints("Accepted")]
|
||||||
|
[ArgHints("region", "URLARG", "the name of the region we are going to")]
|
||||||
|
[ArgHints("x", "URLARG", "X location to teleport to")]
|
||||||
|
[ArgHints("y", "URLARG", "y location to teleport to")]
|
||||||
|
[ArgHints("z", "URLARG", "z location to teleport to")]
|
||||||
|
[Route(HttpVerbs.Get, "/Teleport/{region}/{x}/{y}/{z}/{token}")]
|
||||||
|
public object Teleport(string region, string x, string y, string z, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
bool status = TeleportRequest(new [] { region, x, y, z });
|
||||||
|
if (status == false)
|
||||||
|
{
|
||||||
|
return Failure("Error Unable to Teleport to location", "Teleport", new [] { region, x, y, z });
|
||||||
|
}
|
||||||
|
bot.SetTeleported();
|
||||||
|
return BasicReply("Accepted", "Teleport", new [] { region, x, y, z });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("Attempt to teleport to a new region via a SL url")]
|
||||||
|
[ReturnHintsFailure("slurl is empty")]
|
||||||
|
[ReturnHints("True|False")]
|
||||||
|
[ArgHints("slurl", "Text", "a full SLurl")]
|
||||||
|
[Route(HttpVerbs.Post, "/TeleportSLURL/{token}")]
|
||||||
|
public object TeleportSLURL([FormField] string slurl, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(slurl) == false)
|
||||||
|
{
|
||||||
|
return Failure("slurl is empty", "TeleportSLURL", new [] { slurl });
|
||||||
|
}
|
||||||
|
bot.SetTeleported();
|
||||||
|
return BasicReply(TeleportRequest(new [] { slurl }).ToString(), "TeleportSLURL", new [] { slurl });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool TeleportRequest(string[] args)
|
||||||
|
{
|
||||||
|
getClient().Self.AutoPilotCancel();
|
||||||
|
if (args[0].Contains("http://maps.secondlife.com/secondlife/") == true)
|
||||||
|
{
|
||||||
|
if (bot.TeleportWithSLurl(args[0]) == "ok")
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<string> argvalues = new List<string>(args);
|
||||||
|
if(argvalues.Count == 3)
|
||||||
|
{
|
||||||
|
string regionName = getClient().Network.CurrentSim.Name;
|
||||||
|
argvalues = new List<string>() { regionName };
|
||||||
|
argvalues.AddRange(args);
|
||||||
|
}
|
||||||
|
if (argvalues.Count == 4)
|
||||||
|
{
|
||||||
|
string regionName = argvalues[0];
|
||||||
|
float.TryParse(argvalues[1], out float posX);
|
||||||
|
float.TryParse(argvalues[2], out float posY);
|
||||||
|
float.TryParse(argvalues[3], out float posZ);
|
||||||
|
bot.SetTeleported();
|
||||||
|
bool status = getClient().Self.Teleport(regionName, new Vector3(posX, posY, posZ));
|
||||||
|
bot.ResetAnimations();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
129
SecondBotEvents/Commands/Notecard.cs
Normal file
129
SecondBotEvents/Commands/Notecard.cs
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Notecard : CommandsAPI
|
||||||
|
{
|
||||||
|
public Notecard(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Adds content to the Collection<br/> Also creates the Collection if it does not exist")]
|
||||||
|
[ReturnHintsFailure("Collection value is empty")]
|
||||||
|
[ReturnHintsFailure("Content value is empty")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ArgHints("collection", "URLARG", "The name of the collection")]
|
||||||
|
[ArgHints("content", "String", "The text to add to the collection")]
|
||||||
|
[Route(HttpVerbs.Post, "/NotecardAdd/{collection}/{token}")]
|
||||||
|
public object NotecardAdd(string collection, [FormField] string content, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(collection) == false)
|
||||||
|
{
|
||||||
|
return Failure("Collection value is empty", "NotecardAdd", new [] { collection, content });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(content) == false)
|
||||||
|
{
|
||||||
|
return Failure("Content value is empty", "NotecardAdd", new [] { collection, content });
|
||||||
|
}
|
||||||
|
bot.NotecardAddContent(collection, content);
|
||||||
|
return BasicReply("ok", "NotecardAdd", new [] { collection, content });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Clears the contents of a collection")]
|
||||||
|
[ReturnHintsFailure("Collection value is empty")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ArgHints("collection", "URLARG", "The name of the collection")]
|
||||||
|
[Route(HttpVerbs.Get, "/NotecardClear/{collection}/{token}")]
|
||||||
|
public object NotecardClear(string collection, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(collection) == false)
|
||||||
|
{
|
||||||
|
return Failure("Collection value is empty", "NotecardClear", new [] { collection });
|
||||||
|
}
|
||||||
|
bot.ClearNotecardStorage(collection);
|
||||||
|
return BasicReply("ok", "NotecardClear", new [] { collection });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sends a notecard to a avatar using the text in the prebuilt collection [see NotecardAdd] and also clears the collection just before sending [see NotecardClear]")]
|
||||||
|
[ReturnHintsFailure("Collection value is empty")]
|
||||||
|
[ReturnHintsFailure("Notecardname value is empty")]
|
||||||
|
[ReturnHintsFailure("Invaild avatar uuid")]
|
||||||
|
[ReturnHintsFailure("No content in notecard storage ?")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ArgHints("avatar", "URLARG", "The UUID or Name of an avatar")]
|
||||||
|
[ArgHints("collection", "URLARG", "The name of the collection")]
|
||||||
|
[ArgHints("notecardname", "URLARG", "What to call the created notecard")]
|
||||||
|
[Route(HttpVerbs.Get, "/NotecardSend/{avatar}/{collection}/{notecardname}/{token}")]
|
||||||
|
public object NotecardSend(string avatar, string collection, string notecardname, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(collection) == false)
|
||||||
|
{
|
||||||
|
return Failure("Collection value is empty", "NotecardSend", new [] { avatar, collection, notecardname });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(notecardname) == false)
|
||||||
|
{
|
||||||
|
return Failure("Notecardname value is empty", "NotecardSend", new [] { avatar, collection, notecardname });
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if(avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar uuid", "NotecardSend", new [] { avatar, collection, notecardname });
|
||||||
|
}
|
||||||
|
string content = bot.GetNotecardContent(collection);
|
||||||
|
if (content == null)
|
||||||
|
{
|
||||||
|
return Failure("No content in notecard storage " + collection, "NotecardSend", new [] { avatar, collection, notecardname });
|
||||||
|
}
|
||||||
|
bot.ClearNotecardStorage(collection);
|
||||||
|
return BasicReply(bot.SendNotecard(notecardname, content, avataruuid).ToString(), "NotecardSend", new [] { avatar, collection, notecardname });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Creates and sends a notecard in one command good if you are using HTTP otherwise see [NotecardSend]")]
|
||||||
|
[ReturnHintsFailure("notecardname value is empty")]
|
||||||
|
[ReturnHintsFailure("Content value is empty")]
|
||||||
|
[ReturnHintsFailure("Invaild avatar uuid")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ArgHints("avatar", "URLARG", "The UUID or Name of an avatar")]
|
||||||
|
[ArgHints("content", "String", "The text to add to the collection")]
|
||||||
|
[ArgHints("notecardname", "URLARG", "What to call the created notecard")]
|
||||||
|
[Route(HttpVerbs.Post, "/NotecardDirectSend/{avatar}/{notecardname}/{token}")]
|
||||||
|
public object NotecardDirectSend(string avatar, [FormField] string content, string notecardname, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(notecardname) == false)
|
||||||
|
{
|
||||||
|
return Failure("notecardname value is empty", "NotecardDirectSend", new[] { avatar, content, notecardname });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(content) == false)
|
||||||
|
{
|
||||||
|
return Failure("content value is empty", "NotecardDirectSend", new[] { avatar, content, notecardname });
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar uuid", "NotecardDirectSend", new[] { avatar, content, notecardname });
|
||||||
|
}
|
||||||
|
return BasicReply(bot.SendNotecard(notecardname, content, avataruuid).ToString(), "NotecardDirectSend", new[] { avatar, content, notecardname });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
782
SecondBotEvents/Commands/ParcelCommands.cs
Normal file
782
SecondBotEvents/Commands/ParcelCommands.cs
Normal file
|
|
@ -0,0 +1,782 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public partial class ParcelCommands : CommandsAPI
|
||||||
|
{
|
||||||
|
public ParcelCommands(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sets the current parcel for sale Also marks the parcel for sale")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ReturnHintsFailure("Invaild amount")]
|
||||||
|
[ArgHints("amount", "URLARG", "The amount to sell the parcel for from 1 to 9999999")]
|
||||||
|
[ArgHints("avatar", "URLARG", "Avatar uuid or Firstname Lastname or \"none\" who we are locking the sale to")]
|
||||||
|
[Route(HttpVerbs.Get, "/SetParcelSale/{amount}/{avatar}/{token}")]
|
||||||
|
public object SetParcelSale(string amount,string avatar,string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if(tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "SetParcelSale", new [] { amount, avatar });
|
||||||
|
}
|
||||||
|
if (int.TryParse(amount,out int amountvalue) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild amount", "SetParcelSale", new [] { amount, avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
int minAmount = 1;
|
||||||
|
avataruuid = UUID.Zero;
|
||||||
|
if (avatar != "none")
|
||||||
|
{
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if(avataruuid != UUID.Zero)
|
||||||
|
{
|
||||||
|
minAmount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((amountvalue < minAmount) || (amountvalue > 9999999))
|
||||||
|
{
|
||||||
|
return Failure("Invaild amount", "SetParcelSale", new [] { amount, avatar });
|
||||||
|
}
|
||||||
|
targetparcel.SalePrice = amountvalue;
|
||||||
|
targetparcel.AuthBuyerID = avataruuid;
|
||||||
|
parcel_static.ParcelSetFlag(ParcelFlags.ForSale, targetparcel, true);
|
||||||
|
parcel_static.ParcelSetFlag(ParcelFlags.ForSaleObjects, targetparcel, false);
|
||||||
|
targetparcel.Update(getClient().Network.CurrentSim, false);
|
||||||
|
return Failure("ok", "SetParcelSale", new [] { amount, avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Gets the parcel Dwell (Traffic) value and returns it via the reply target")]
|
||||||
|
[ReturnHints("traffic value")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetParcelTraffic/{token}")]
|
||||||
|
public object GetParcelTraffic(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "GetParcelTraffic");
|
||||||
|
}
|
||||||
|
return BasicReply(targetparcel.Dwell.ToString(), "GetParcelTraffic");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Changes the parcel landing mode to point and sets the landing point")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ReturnHintsFailure("Invaild amount")]
|
||||||
|
[ArgHints("x", "URLARG", "X point for landing")]
|
||||||
|
[ArgHints("y", "URLARG", "Y point for landing")]
|
||||||
|
[ArgHints("z", "URLARG", "Z point for landing")]
|
||||||
|
[Route(HttpVerbs.Get, "/SetParcelLandingZone/{x}/{y}/{z}/{token}")]
|
||||||
|
public object SetParcelLandingZone(string x, string y, string z, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "SetParcelLandingZone", new [] { x, y, z });
|
||||||
|
}
|
||||||
|
if(int.TryParse(x,out int X) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unable to process landing point x value", "SetParcelLandingZone", new [] { x, y, z });
|
||||||
|
}
|
||||||
|
if (int.TryParse(y, out int Y) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unable to process landing point y value", "SetParcelLandingZone", new [] { x, y, z });
|
||||||
|
}
|
||||||
|
if (int.TryParse(z, out int Z) == false)
|
||||||
|
{
|
||||||
|
return Failure("Unable to process landing point z value", "SetParcelLandingZone", new [] { x, y, z });
|
||||||
|
}
|
||||||
|
targetparcel.Landing = LandingType.LandingPoint;
|
||||||
|
targetparcel.UserLocation = new Vector3(X, Y, Z);
|
||||||
|
targetparcel.Update(getClient().Network.CurrentSim, false);
|
||||||
|
return BasicReply("ok", "SetParcelLandingZone", new [] { x, y, z });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("Updates the current parcels name")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ReturnHintsFailure("Parcel name is empty")]
|
||||||
|
[ArgHints("name", "URLARG", "The new name of the parcel")]
|
||||||
|
[Route(HttpVerbs.Get, "/SetParcelName/{name}/{token}")]
|
||||||
|
public object SetParcelName(string name, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "SetParcelName", new [] { name });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(name) == false)
|
||||||
|
{
|
||||||
|
return Failure("Parcel name is empty", "SetParcelName", new [] { name });
|
||||||
|
}
|
||||||
|
targetparcel.Name = name;
|
||||||
|
targetparcel.Update(getClient().Network.CurrentSim, false);
|
||||||
|
return BasicReply("ok", "SetParcelName", new [] { name });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Updates the current parcels description")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ArgHints("desc", "Text", "The new desc of the parcel")]
|
||||||
|
[Route(HttpVerbs.Post, "/SetParcelDesc/{token}")]
|
||||||
|
public object SetParcelDesc([FormField] string desc, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "SetParcelDesc", new [] { desc });
|
||||||
|
}
|
||||||
|
targetparcel.Desc = desc;
|
||||||
|
targetparcel.Update(getClient().Network.CurrentSim, false);
|
||||||
|
return BasicReply("ok", "SetParcelDesc", new [] { desc });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Fetchs the current parcels desc")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetParcelDesc/{token}")]
|
||||||
|
public object GetParcelDesc(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "GetParcelDesc");
|
||||||
|
}
|
||||||
|
return BasicReply(targetparcel.Desc, "GetParcelDesc");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("gets the flags for the parcel")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetParcelFlags/{token}")]
|
||||||
|
public object GetParcelFlags(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "GetParcelFlags");
|
||||||
|
}
|
||||||
|
Dictionary<string, ParcelFlags> flags = parcel_static.get_flags_list();
|
||||||
|
Dictionary<string, string> collection = new Dictionary<string, string>();
|
||||||
|
foreach (ParcelFlags cfg in flags.Values)
|
||||||
|
{
|
||||||
|
collection.Add(cfg.ToString(), targetparcel.Flags.HasFlag(cfg).ToString());
|
||||||
|
}
|
||||||
|
SuccessNoReturn("GetParcelFlags");
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Ejects an avatar")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Invaild avatar")]
|
||||||
|
[ArgHints("avatar", "URLARG", "uuid of the avatar or Firstname Lastname")]
|
||||||
|
[Route(HttpVerbs.Get, "/ParcelEject/{avatar}/{token}")]
|
||||||
|
public object ParcelEject(string avatar,string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if(avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar", "ParcelEject", new [] { avatar });
|
||||||
|
}
|
||||||
|
getClient().Parcels.EjectUser(avataruuid, false);
|
||||||
|
return BasicReply("ok", "ParcelEject", new [] { avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Abandons the parcel the bot is currently on, returning it to Linden's or Estate owner")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[Route(HttpVerbs.Get, "/AbandonLand/{token}")]
|
||||||
|
public object AbandonLand(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "AbandonLand");
|
||||||
|
}
|
||||||
|
getClient().Parcels.ReleaseParcel(getClient().Network.CurrentSim, targetparcel.LocalID);
|
||||||
|
return BasicReply("ok", "AbandonLand");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("Bans an avatar from a parcel")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ReturnHintsFailure("Invaild avatar")]
|
||||||
|
[ReturnHintsFailure("Avatar is in the blacklist")]
|
||||||
|
[ArgHints("avatar", "URLARG", "uuid of the avatar or Firstname Lastname")]
|
||||||
|
[Route(HttpVerbs.Get, "/ParcelBan/{avatar}/{token}")]
|
||||||
|
public object ParcelBan(string avatar, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "ParcelBan", new [] { avatar });
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar", "ParcelBan", new [] { avatar });
|
||||||
|
}
|
||||||
|
bool alreadyBanned = false;
|
||||||
|
foreach (ParcelAccessEntry E in targetparcel.AccessBlackList)
|
||||||
|
{
|
||||||
|
if (E.AgentID == avataruuid)
|
||||||
|
{
|
||||||
|
alreadyBanned = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (alreadyBanned == true)
|
||||||
|
{
|
||||||
|
return BasicReply("Avatar is in the blacklist", "ParcelBan", new [] { avatar });
|
||||||
|
}
|
||||||
|
ParcelAccessEntry entry = new ParcelAccessEntry();
|
||||||
|
entry.AgentID = avataruuid;
|
||||||
|
entry.Flags = AccessList.Ban;
|
||||||
|
entry.Time = new System.DateTime(3030, 03, 03);
|
||||||
|
targetparcel.AccessBlackList.Add(entry);
|
||||||
|
targetparcel.Update(getClient().Network.CurrentSim, false);
|
||||||
|
return BasicReply("ok", "ParcelBan", new [] { avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Unbans an avatar from a parcel")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ReturnHintsFailure("Invaild avatar")]
|
||||||
|
[ReturnHintsFailure("Avatar is already unbanned")]
|
||||||
|
[ArgHints("avatar", "URLARG", "uuid of the avatar or Firstname Lastname")]
|
||||||
|
[Route(HttpVerbs.Get, "/ParcelUnBan/{avatar}/{token}")]
|
||||||
|
public object ParcelUnBan(string avatar, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "ParcelUnBan", new [] { avatar });
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar", "ParcelUnBan", new [] { avatar });
|
||||||
|
}
|
||||||
|
bool alreadyBanned = false;
|
||||||
|
ParcelAccessEntry removeentry = new ParcelAccessEntry();
|
||||||
|
foreach (ParcelAccessEntry E in targetparcel.AccessBlackList)
|
||||||
|
{
|
||||||
|
if (E.AgentID == avataruuid)
|
||||||
|
{
|
||||||
|
alreadyBanned = true;
|
||||||
|
removeentry = E;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (alreadyBanned == false)
|
||||||
|
{
|
||||||
|
return BasicReply("Avatar is already unbanned", "ParcelUnBan", new [] { avatar });
|
||||||
|
}
|
||||||
|
targetparcel.AccessBlackList.Remove(removeentry);
|
||||||
|
targetparcel.Update(getClient().Network.CurrentSim, false);
|
||||||
|
return BasicReply("ok", "ParcelUnBan", new [] { avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("Updates the current parcels name")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ArgHints("musicurl", "URLARG", "The new name of the parcel")]
|
||||||
|
[Route(HttpVerbs.Get, "/SetParcelMusic/{musicurl}/{token}")]
|
||||||
|
public object SetParcelMusic(string musicurl, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "SetParcelMusic", new [] { musicurl });
|
||||||
|
}
|
||||||
|
bool status = parcel_static.set_parcel_music(bot, targetparcel, musicurl);
|
||||||
|
return BasicReply(status.ToString(), "SetParcelMusic", new [] { musicurl });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Updates the current parcels name")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ReturnHintsFailure("Incorrect perms to control parcel")]
|
||||||
|
[ReturnHintsFailure("No accepted flags")]
|
||||||
|
[ReturnHintsFailure("Unable to set flag ...")]
|
||||||
|
[ReturnHintsFailure("Flag: ? is unknown")]
|
||||||
|
[ReturnHintsFailure("Flag: ? missing \"=\"")]
|
||||||
|
[ArgHints("escapedflagdata", "Text", "repeatable flag data split by ::: formated Flag=True|False")]
|
||||||
|
[Route(HttpVerbs.Post, "/SetParcelFlag/{escapedflagdata}/{token}")]
|
||||||
|
public object SetParcelFlag([FormField] string escapedflagdata, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "SetParcelFlag", new [] { escapedflagdata });
|
||||||
|
}
|
||||||
|
List<string> acceptablewords = new List<string>();
|
||||||
|
Dictionary<string, ParcelFlags> flags = parcel_static.get_flags_list();
|
||||||
|
acceptablewords.AddRange(new[] { "True", "False" });
|
||||||
|
|
||||||
|
Dictionary<string, bool> setflags = new Dictionary<string, bool>();
|
||||||
|
string[] args = escapedflagdata.Split(":::");
|
||||||
|
foreach (string a in args)
|
||||||
|
{
|
||||||
|
string[] parts = a.Split('=', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (parts.Length != 2)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("Flag: " + a + " missing \"=\"");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (flags.ContainsKey(parts[0]) == false)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("Flag: " + parts[0] + " is unknown");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (acceptablewords.Contains(parts[1]) == false)
|
||||||
|
{
|
||||||
|
LogFormater.Crit("Unable to set flag " + parts[0] + " to : " + parts[1] + "");
|
||||||
|
}
|
||||||
|
setflags.Add(parts[0], Convert.ToBoolean(parts[1]));
|
||||||
|
}
|
||||||
|
if (setflags.Count == 0)
|
||||||
|
{
|
||||||
|
return Failure("No accepted flags", "SetParcelFlag", new [] { escapedflagdata });
|
||||||
|
}
|
||||||
|
if (parcel_static.has_parcel_perm(targetparcel, bot) == false)
|
||||||
|
{
|
||||||
|
return Failure("Incorrect perms to control parcel", "SetParcelFlag", new [] { escapedflagdata });
|
||||||
|
}
|
||||||
|
foreach (KeyValuePair<string, bool> cfg in setflags)
|
||||||
|
{
|
||||||
|
if (flags.ContainsKey(cfg.Key) == true)
|
||||||
|
{
|
||||||
|
parcel_static.ParcelSetFlag(flags[cfg.Key], targetparcel, cfg.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
targetparcel.Update(getClient().Network.CurrentSim, false);
|
||||||
|
return BasicReply("Applying perms", "SetParcelFlag", new [] { escapedflagdata });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Returns all objects from the current parcel for the selected avatar")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ReturnHintsFailure("Invaild avatar UUID")]
|
||||||
|
[ArgHints("avatar", "URLARG", "avatar uuid or Firstname Lastname")]
|
||||||
|
[Route(HttpVerbs.Get, "/ParcelReturnTargeted/{avatar}/{token}")]
|
||||||
|
public object ParcelReturnTargeted(string avatar, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "ParcelReturnTargeted", new [] { avatar });
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar UUID", "ParcelReturnTargeted", new [] { avatar });
|
||||||
|
}
|
||||||
|
getClient().Parcels.ReturnObjects(getClient().Network.CurrentSim, targetparcel.LocalID, ObjectReturnType.None, new List<UUID>() { avataruuid });
|
||||||
|
return BasicReply("ok", "ParcelReturnTargeted", new [] { avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("transfers the current parcel ownership to the assigned group")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ReturnHintsFailure("Invaild group uuid")]
|
||||||
|
[ReturnHintsFailure("Not in group")]
|
||||||
|
[Route(HttpVerbs.Get, "/ParcelDeedToGroup/{group}/{token}")]
|
||||||
|
public object ParcelDeedToGroup(string group, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "ParcelDeedToGroup", new [] { group });
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(group, out UUID groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild group uuid", "ParcelDeedToGroup", new [] { group });
|
||||||
|
}
|
||||||
|
if (bot.MyGroups.ContainsKey(groupuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Not in group", "ParcelDeedToGroup", new [] { group });
|
||||||
|
}
|
||||||
|
targetparcel.GroupID = groupuuid;
|
||||||
|
targetparcel.Update(getClient().Network.CurrentSim, false);
|
||||||
|
Thread.Sleep(500);
|
||||||
|
getClient().Parcels.DeedToGroup(getClient().Network.CurrentSim, targetparcel.LocalID, groupuuid);
|
||||||
|
return BasicReply("ok", "ParcelDeedToGroup", new [] { group });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Attempts to buy the parcel the bot is standing on, the amount must match the sale price for the land!")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ReturnHintsFailure("Parcel not for sale")]
|
||||||
|
[ReturnHintsFailure("Parcel not for sale")]
|
||||||
|
[ReturnHintsFailure("Parcel sale locked to other avatars")]
|
||||||
|
[ReturnHintsFailure("Parcel sale price and amount do not match")]
|
||||||
|
[ReturnHintsFailure("Invaild amount")]
|
||||||
|
[ArgHints("amount", "URLARG", "amount to pay for the parcel (min 1)")]
|
||||||
|
[Route(HttpVerbs.Get, "/ParcelBuy/{amount}/{token}")]
|
||||||
|
public object ParcelBuy(string amount, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "ParcelBuy", new [] { amount });
|
||||||
|
}
|
||||||
|
if ((targetparcel.AuthBuyerID != UUID.Zero) && (targetparcel.AuthBuyerID != getClient().Self.AgentID))
|
||||||
|
{
|
||||||
|
return Failure("Parcel sale locked to other avatars", "ParcelBuy", new[] { amount });
|
||||||
|
}
|
||||||
|
int minAmount = 1;
|
||||||
|
if (targetparcel.AuthBuyerID == getClient().Self.AgentID)
|
||||||
|
{
|
||||||
|
minAmount = 0;
|
||||||
|
}
|
||||||
|
if (int.TryParse(amount, out int amountvalue) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild amount", "ParcelBuy", new [] { amount });
|
||||||
|
}
|
||||||
|
if (amountvalue < minAmount)
|
||||||
|
{
|
||||||
|
return Failure("Invaild amount", "ParcelBuy", new [] { amount });
|
||||||
|
};
|
||||||
|
if (targetparcel.Flags.HasFlag(ParcelFlags.ForSale) == false)
|
||||||
|
{
|
||||||
|
return Failure("Parcel not for sale", "ParcelBuy", new [] { amount });
|
||||||
|
}
|
||||||
|
if (targetparcel.SalePrice != amountvalue)
|
||||||
|
{
|
||||||
|
return Failure("Parcel sale price and amount do not match", "ParcelBuy", new [] { amount });
|
||||||
|
}
|
||||||
|
getClient().Parcels.Buy(getClient().Network.CurrentSim, targetparcel.LocalID, false, UUID.Zero, false, targetparcel.Area, amountvalue);
|
||||||
|
return BasicReply("ok", "ParcelBuy", new [] { amount });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Freezes an avatar")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Invaild avatar UUID")]
|
||||||
|
[ReturnHintsFailure("Invaild state")]
|
||||||
|
[ArgHints("avatar", "URLARG", "avatar uuid or Firstname Lastname")]
|
||||||
|
[ArgHints("state", "URLARG", "setting state to false will unfreeze or true to freeze")]
|
||||||
|
[Route(HttpVerbs.Get, "/ParcelFreeze/{avatar}/{state}/{token}")]
|
||||||
|
public object ParcelFreeze(string avatar, string state, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bool.TryParse(state, out bool freezestate) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild state", "ParcelFreeze", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("Invaild avatar UUID", "ParcelFreeze", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
getClient().Parcels.FreezeUser(avataruuid, freezestate);
|
||||||
|
return BasicReply("ok", "ParcelFreeze", new [] { avatar, state });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("Fetchs the parcel ban list of the parcel the bot is currently on<br/>If the name returned is lookup the bot is currently requesting the avatar name")]
|
||||||
|
[ReturnHintsFailure("json object: GetParcelBanlistObject")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetParcelBanlist/{token}")]
|
||||||
|
public object GetParcelBanlist(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "GetParcelBanlist");
|
||||||
|
}
|
||||||
|
GetParcelBanlistObject reply = new GetParcelBanlistObject();
|
||||||
|
int delays = 0;
|
||||||
|
bool haslookup = true;
|
||||||
|
while ((haslookup == true) && (delays < 3))
|
||||||
|
{
|
||||||
|
haslookup = false;
|
||||||
|
foreach (ParcelAccessEntry e in targetparcel.AccessBlackList)
|
||||||
|
{
|
||||||
|
if (e.AgentID != UUID.Zero)
|
||||||
|
{
|
||||||
|
if (bot.FindAvatarKey2Name(e.AgentID) == "lookup")
|
||||||
|
{
|
||||||
|
haslookup = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(haslookup == true)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
delays++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (ParcelAccessEntry e in targetparcel.AccessBlackList)
|
||||||
|
{
|
||||||
|
string name = bot.FindAvatarKey2Name(e.AgentID);
|
||||||
|
reply.entrys.Add(e.AgentID, name);
|
||||||
|
}
|
||||||
|
reply.reportedEntrys = targetparcel.AccessBlackList.Count;
|
||||||
|
reply.delay = delays * 1000;
|
||||||
|
reply.parcelName = targetparcel.Name;
|
||||||
|
reply.regionName = getClient().Network.CurrentSim.Name;
|
||||||
|
return BasicReply(JsonConvert.SerializeObject(reply), "GetParcelBanlist");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Returns a rezzed object")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Invaild object uuid")]
|
||||||
|
[ReturnHintsFailure("Unable to find object")]
|
||||||
|
[ArgHints("objectuuid", "URLARG", "object UUID to unrez")]
|
||||||
|
[Route(HttpVerbs.Get, "/UnRezObject/{objectuuid}/{token}")]
|
||||||
|
public object UnRezObject(string objectuuid,string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(objectuuid, out UUID targetobject) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild object uuid", "UnRezObject", new [] { objectuuid });
|
||||||
|
}
|
||||||
|
bool found = false;
|
||||||
|
Dictionary<uint, Primitive> objects_copy = getClient().Network.CurrentSim.ObjectsPrimitives.Copy();
|
||||||
|
foreach (KeyValuePair<uint, Primitive> Obj in objects_copy)
|
||||||
|
{
|
||||||
|
if (Obj.Value.ID == targetobject)
|
||||||
|
{
|
||||||
|
getClient().Inventory.RequestDeRezToInventory(Obj.Key);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(found == false)
|
||||||
|
{
|
||||||
|
return Failure("Unable to find object", "UnRezObject", new [] { objectuuid });
|
||||||
|
}
|
||||||
|
return BasicReply("ok", "UnRezObject", new [] { objectuuid });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Updates the current parcels media settings \n" +
|
||||||
|
"MediaAutoScale=Bool (True|False)\n" +
|
||||||
|
"MediaLoop=Bool (True|False)\n" +
|
||||||
|
"MediaID=UUID (Texture)\n" +
|
||||||
|
"MediaURL=String\n" +
|
||||||
|
"MediaDesc=String\n" +
|
||||||
|
"MediaHeight=Int (256 to 1024)\n" +
|
||||||
|
"MediaWidth=Int (256 to 1024)\n" +
|
||||||
|
"MediaType=String [\"IMG-PNG\",\"IMG-JPG\",\"VID-MP4\",\"VID-AVI\" or \"Custom-MIME_TYPE_CODE\"]"
|
||||||
|
)]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Error not in a sim")]
|
||||||
|
[ReturnHintsFailure("Parcel data not ready")]
|
||||||
|
[ArgHints("escapedflagdata", "Text", "repeatable flag data split by ::: formated Flag=True|False")]
|
||||||
|
[Route(HttpVerbs.Get, "/ParcelSetMedia/{token}")]
|
||||||
|
public object ParcelSetMedia([FormField] string escapedflagdata, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
KeyValuePair<bool, string> tests = SetupCurrentParcel();
|
||||||
|
if (tests.Key == false)
|
||||||
|
{
|
||||||
|
return Failure(tests.Value, "ParcelSetMedia", new [] { escapedflagdata });
|
||||||
|
}
|
||||||
|
string[] args = escapedflagdata.Split(":::");
|
||||||
|
foreach (string A in args)
|
||||||
|
{
|
||||||
|
string[] bits = A.Split('=');
|
||||||
|
if (bits.Length == 2)
|
||||||
|
{
|
||||||
|
if (bits[0] == "MediaType")
|
||||||
|
{
|
||||||
|
UpdateParcel_MediaType(targetparcel, bits[1]);
|
||||||
|
}
|
||||||
|
else if ((bits[0] == "MediaWidth") || (bits[0] == "MediaHeight"))
|
||||||
|
{
|
||||||
|
if (int.TryParse(bits[1], out int size) == true)
|
||||||
|
{
|
||||||
|
if ((size >= 256) || (size <= 1024))
|
||||||
|
{
|
||||||
|
if (bits[0] == "MediaHeight")
|
||||||
|
{
|
||||||
|
targetparcel.Media.MediaHeight = size;
|
||||||
|
}
|
||||||
|
else if (bits[0] == "MediaWidth")
|
||||||
|
{
|
||||||
|
targetparcel.Media.MediaWidth = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bits[0] == "MediaID")
|
||||||
|
{
|
||||||
|
if (UUID.TryParse(bits[1], out UUID texture) == true)
|
||||||
|
{
|
||||||
|
targetparcel.Media.MediaID = texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bits[0] == "MediaURL")
|
||||||
|
{
|
||||||
|
targetparcel.Media.MediaURL = bits[1];
|
||||||
|
}
|
||||||
|
else if (bits[0] == "MediaDesc")
|
||||||
|
{
|
||||||
|
targetparcel.Media.MediaDesc = bits[1];
|
||||||
|
}
|
||||||
|
else if (bits[0] == "MediaAutoScale")
|
||||||
|
{
|
||||||
|
if (bool.TryParse(bits[1], out bool output) == true)
|
||||||
|
{
|
||||||
|
targetparcel.Media.MediaAutoScale = output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bits[0] == "MediaLoop")
|
||||||
|
{
|
||||||
|
if (bool.TryParse(bits[1], out bool output) == true)
|
||||||
|
{
|
||||||
|
targetparcel.Media.MediaLoop = output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
targetparcel.Update(getClient().Network.CurrentSim, false);
|
||||||
|
return BasicReply("ok", "ParcelSetMedia", new [] { escapedflagdata });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool UpdateParcel_MediaType(Parcel targetparcel, string value)
|
||||||
|
{
|
||||||
|
if (value == "IMG-PNG")
|
||||||
|
{
|
||||||
|
targetparcel.Media.MediaType = "image/png";
|
||||||
|
}
|
||||||
|
else if (value == "IMG-JPG")
|
||||||
|
{
|
||||||
|
targetparcel.Media.MediaType = "image/jpeg";
|
||||||
|
}
|
||||||
|
else if (value == "VID-MP4")
|
||||||
|
{
|
||||||
|
targetparcel.Media.MediaType = "video/mp4";
|
||||||
|
}
|
||||||
|
else if (value == "VID-AVI")
|
||||||
|
{
|
||||||
|
targetparcel.Media.MediaType = "video/x-msvideo";
|
||||||
|
}
|
||||||
|
else if (value.StartsWith("Custom-") == true)
|
||||||
|
{
|
||||||
|
string mime = value;
|
||||||
|
mime = mime.Replace("Custom-", "");
|
||||||
|
targetparcel.Media.MediaType = mime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetParcelBanlistObject
|
||||||
|
{
|
||||||
|
public Dictionary<UUID, string> entrys = new Dictionary<UUID, string>();
|
||||||
|
public string parcelName = "";
|
||||||
|
public string regionName = "";
|
||||||
|
public int delay = 0;
|
||||||
|
public int reportedEntrys = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
273
SecondBotEvents/Commands/Self.cs
Normal file
273
SecondBotEvents/Commands/Self.cs
Normal file
|
|
@ -0,0 +1,273 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class Self : CommandsAPI
|
||||||
|
{
|
||||||
|
public Self(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Makes the bot teleport to its home region")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[Route(HttpVerbs.Get, "/GoHome/{token}")]
|
||||||
|
public object GoHome(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
bot.GotoNextHomeRegion();
|
||||||
|
return BasicReply("ok", "GoHome");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Makes the bot turn to face avatar and point at them (if found)")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Cant find UUID in sim")]
|
||||||
|
[Route(HttpVerbs.Get, "/PointAt/{avatar}/{token}")]
|
||||||
|
public object PointAt(string avatar, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (getClient().Network.CurrentSim.AvatarPositions.ContainsKey(avataruuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Cant find UUID in sim", "PointAt", new [] { avatar });
|
||||||
|
}
|
||||||
|
bot.ResetAnimations();
|
||||||
|
getClient().Self.Stand();
|
||||||
|
getClient().Self.Movement.TurnToward(getClient().Network.CurrentSim.AvatarPositions[avataruuid]);
|
||||||
|
getClient().Self.Movement.SendUpdate();
|
||||||
|
getClient().Self.AnimationStart(Animations.POINT_YOU, true);
|
||||||
|
getClient().Self.PointAtEffect(getClient().Self.AgentID, avataruuid, new Vector3d(0, 0, 0), PointAtType.Select, UUID.Random());
|
||||||
|
getClient().Self.BeamEffect(getClient().Self.AgentID, avataruuid, new Vector3d(0, 0, 2), new Color4(255, 255, 255, 1), (float)3.0, UUID.Random());
|
||||||
|
return BasicReply("ok", "PointAt", new [] { avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Reads a value from the KeyValue storage (temp unless SQL is enabled)")]
|
||||||
|
[ReturnHints("value")]
|
||||||
|
[ReturnHintsFailure("Unknown Key: KeyName")]
|
||||||
|
[ArgHints("Key", "URLARG", "the key we are trying to read from")]
|
||||||
|
[Route(HttpVerbs.Get, "/ReadKeyValue/{Key}/{token}")]
|
||||||
|
public object ReadKeyValue(string Key, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.HaveLocalKeyStorage(Key) == true)
|
||||||
|
{
|
||||||
|
return BasicReply(bot.ReadLocalKeyStorage(Key), "ReadKeyValue");
|
||||||
|
}
|
||||||
|
return Failure("Unknown Key: "+Key, "ReadKeyValue");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("sets a value for KeyValue storage (temp unless SQL is enabled)")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Key is empty")]
|
||||||
|
[ReturnHintsFailure("Value is empty")]
|
||||||
|
[ArgHints("Key", "URLARG", "the key we are trying to set")]
|
||||||
|
[ArgHints("Value", "string", "the value we are tring to put on the key")]
|
||||||
|
[Route(HttpVerbs.Post, "/SetKeyValue/{Key}/{token}")]
|
||||||
|
public object SetKeyValue(string Key, [FormField] string Value, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.isempty(Key) == false)
|
||||||
|
{
|
||||||
|
return Failure("Key is empty", "SetKeyValue", new[] { Key, Value });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.isempty(Value) == false)
|
||||||
|
{
|
||||||
|
return Failure("Value is empty", "SetKeyValue", new[] { Key, Value });
|
||||||
|
}
|
||||||
|
bot.setLocalKeyStorage(Key, Value);
|
||||||
|
return BasicReply("ok", "SetKeyValue");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Reads a value from the KeyValue storage (temp unless SQL is enabled)")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Key is empty")]
|
||||||
|
[ArgHints("Key", "URLARG", "the key we are trying to clear")]
|
||||||
|
[Route(HttpVerbs.Get, "/ClearKeyValue/{Key}/{token}")]
|
||||||
|
public object ClearKeyValue(string Key, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.isempty(Key) == false)
|
||||||
|
{
|
||||||
|
return Failure("Key is empty", "SetKeyValue", new[] { Key });
|
||||||
|
}
|
||||||
|
bot.clearLocalKeyStorage(Key);
|
||||||
|
return BasicReply("ok", "SetKeyValue");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Makes the bot sit on the ground or on a object if it can see it")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[ReturnHintsFailure("Invaild object UUID")]
|
||||||
|
[ArgHints("target", "URLARG", "ground or a object UUID")]
|
||||||
|
[Route(HttpVerbs.Get, "/Sit/{target}/{token}")]
|
||||||
|
public object Sit(string target, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (target == "ground")
|
||||||
|
{
|
||||||
|
getClient().Self.SitOnGround();
|
||||||
|
return BasicReply("ok", "Sit", new [] { target });
|
||||||
|
}
|
||||||
|
if(UUID.TryParse(target,out UUID objectuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild object UUID", "Sit", new [] { target });
|
||||||
|
}
|
||||||
|
getClient().Self.RequestSit(objectuuid, Vector3.Zero);
|
||||||
|
return BasicReply("ok", "Sit", new [] { target });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Makes the bot stand up if sitting (also resets animations)")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[Route(HttpVerbs.Get, "/Stand/{token}")]
|
||||||
|
public object Stand(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
getClient().Self.Stand();
|
||||||
|
bot.ResetAnimations();
|
||||||
|
return BasicReply("ok", "Stand");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Makes the bot sit on the ground or on a object if it can see it")]
|
||||||
|
[ReturnHints("true|false")]
|
||||||
|
[ReturnHintsFailure("Invaild object UUID")]
|
||||||
|
[ReturnHintsFailure("Unable to see object")]
|
||||||
|
[ArgHints("target", "URLARG", "object UUID")]
|
||||||
|
[Route(HttpVerbs.Get, "/ClickObject/{object}/{token}")]
|
||||||
|
public object ClickObject(string target, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(target, out UUID objectuuid) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild object UUID", "ClickObject", new [] { target });
|
||||||
|
}
|
||||||
|
|
||||||
|
getClient().Self.PointAtEffect(getClient().Self.AgentID, objectuuid, new Vector3d(0, 0, 0), PointAtType.Select, new UUID("1df9eb92-62fa-15e5-4bfb-5931f1525274"));
|
||||||
|
|
||||||
|
Dictionary<uint, Primitive> objectsentrys = getClient().Network.CurrentSim.ObjectsPrimitives.Copy();
|
||||||
|
|
||||||
|
bool found_object = false;
|
||||||
|
foreach (KeyValuePair<uint, Primitive> entry in objectsentrys)
|
||||||
|
{
|
||||||
|
if (entry.Value.ID == objectuuid)
|
||||||
|
{
|
||||||
|
getClient().Objects.ClickObject(getClient().Network.CurrentSim, entry.Key);
|
||||||
|
found_object = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BasicReply(found_object.ToString(), "ClickObject", new [] { target });
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Makes the bot kill itself you monster")]
|
||||||
|
[ReturnHints("ok")]
|
||||||
|
[Route(HttpVerbs.Get, "/Logoff/{token}")]
|
||||||
|
public object Logoff(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (bot.KillMe == false)
|
||||||
|
{
|
||||||
|
getClient().Self.Chat("Laters im out", 0, ChatType.Normal);
|
||||||
|
bot.KillMePlease();
|
||||||
|
}
|
||||||
|
return BasicReply("ok", "Logoff");
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Gets the last 5 commands issued to the bot")]
|
||||||
|
[ReturnHints("list of commands")]
|
||||||
|
[Route(HttpVerbs.Get, "/GetLastCommands/{token}")]
|
||||||
|
public object GetLastCommands(string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
SuccessNoReturn("GetLastCommands");
|
||||||
|
return bot.GetLastCommands(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[About("Sets the bot to accept a request type from the avatar (or a object owned by the avatar)\n " +
|
||||||
|
"friend: friend request \n " +
|
||||||
|
"group: group invite \n " +
|
||||||
|
"animation: trigger animation request [from a object]\n" +
|
||||||
|
"teleport: teleport lure\n" +
|
||||||
|
"inventory: Inventory transfer\n" +
|
||||||
|
"command: A non signed command")]
|
||||||
|
[ReturnHintsFailure("avatar lookup")]
|
||||||
|
[ReturnHintsFailure("Invaild state")]
|
||||||
|
[ReturnHintsFailure("Invaild sticky")]
|
||||||
|
[ReturnHintsFailure("Invaild flag")]
|
||||||
|
[ArgHints("avatar", "URLARG", "avatar uuid or Firstname Lastname")]
|
||||||
|
[ArgHints("flag", "URLARG", "friend, group, animation, teleport, inventory or command")]
|
||||||
|
[ArgHints("state", "URLARG", "State to set the flag to true or false")]
|
||||||
|
[ArgHints("sticky", "URLARG", "if true the permissing will not expire after the first use otherwise false")]
|
||||||
|
[Route(HttpVerbs.Get, "/SetPermFlag/{avatar}/{flag}/{state}/{sticky}/{token}")]
|
||||||
|
public object SetPermFlag(string avatar, string flag, string state, string sticky, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
ProcessAvatar(avatar);
|
||||||
|
if (avataruuid == UUID.Zero)
|
||||||
|
{
|
||||||
|
return Failure("avatar lookup", "SetPermFlag", new [] { avatar, flag, state, sticky });
|
||||||
|
}
|
||||||
|
bool stateflag = false;
|
||||||
|
bool stickyflag = false;
|
||||||
|
if(bool.TryParse(state,out stateflag) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild state", "SetPermFlag", new [] { avatar, flag, state, sticky });
|
||||||
|
}
|
||||||
|
if (bool.TryParse(sticky, out stickyflag) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild sticky", "SetPermFlag", new [] { avatar, flag, state, sticky });
|
||||||
|
}
|
||||||
|
string[] AcceptedFlags = new [] { "friend", "group", "animation", "teleport", "command", "inventory" };
|
||||||
|
if (AcceptedFlags.Contains(flag) == false)
|
||||||
|
{
|
||||||
|
return Failure("Invaild flag", "SetPermFlag", new [] { avatar, flag, state, sticky });
|
||||||
|
}
|
||||||
|
if (stateflag == true)
|
||||||
|
{
|
||||||
|
bot.Add_action_from(flag, avataruuid, bot.FindAvatarKey2Name(avataruuid), stickyflag);
|
||||||
|
return BasicReply("Added perm: " + flag + " Sticky: " + stickyflag.ToString(), "SetPermFlag", new [] { avatar, flag, state, sticky });
|
||||||
|
}
|
||||||
|
bot.Remove_action_from(flag, avataruuid, stickyflag);
|
||||||
|
return BasicReply("Removed perm: " + flag + " Sticky: " + stickyflag.ToString(), "SetPermFlag", new [] { avatar, flag, state, sticky });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
99
SecondBotEvents/Commands/StreamAdmin.cs
Normal file
99
SecondBotEvents/Commands/StreamAdmin.cs
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Routing;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using RestSharp;
|
||||||
|
using SecondBotEvents.Services;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Commands
|
||||||
|
{
|
||||||
|
public class StreamAdmin : CommandsAPI
|
||||||
|
{
|
||||||
|
public StreamAdmin(EventsSecondBot setmaster) : base(setmaster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[About("A streamadin command")]
|
||||||
|
[ReturnHints("True|False")]
|
||||||
|
[ReturnHintsFailure("Bad reply: ...")]
|
||||||
|
[ReturnHintsFailure("Endpoint is empty")]
|
||||||
|
[ReturnHintsFailure("Endpointcode is empty")]
|
||||||
|
[ReturnHintsFailure("HTTP status code: ...")]
|
||||||
|
[ReturnHintsFailure("Error: ...")]
|
||||||
|
[ReturnHintsFailure("Notecard title is to short")]
|
||||||
|
[ArgHints("endpoint","Text","The end point")]
|
||||||
|
[ArgHints("endpointcode", "Text", "The end point code")]
|
||||||
|
[Route(HttpVerbs.Post, "/FetchNextNotecard/{token}")]
|
||||||
|
public object FetchNextNotecard([FormField] string endpoint, [FormField] string endpointcode, string token)
|
||||||
|
{
|
||||||
|
if (AllowToken(token) == false)
|
||||||
|
{
|
||||||
|
return Failure("Token not accepted");
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(endpoint) == false)
|
||||||
|
{
|
||||||
|
return Failure("Endpoint is empty", "FetchNextNotecard", new [] { endpoint, endpointcode });
|
||||||
|
}
|
||||||
|
if (SecondbotHelpers.notempty(endpointcode) == false)
|
||||||
|
{
|
||||||
|
return Failure("Endpointcode is empty", "FetchNextNotecard", new [] { endpoint, endpointcode });
|
||||||
|
}
|
||||||
|
|
||||||
|
string attempt_endpoint = endpoint + "sys.php";
|
||||||
|
token = SecondbotHelpers.GetSHA1(SecondbotHelpers.UnixTimeNow().ToString() + "NotecardNext" + endpointcode);
|
||||||
|
var client = new RestClient(attempt_endpoint);
|
||||||
|
var request = new RestRequest("Notecard/Next", Method.Post);
|
||||||
|
string unixtime = SecondbotHelpers.UnixTimeNow().ToString();
|
||||||
|
request.AddParameter("token", token);
|
||||||
|
request.AddParameter("unixtime", unixtime);
|
||||||
|
request.AddParameter("method", "Notecard");
|
||||||
|
request.AddParameter("action", "Next");
|
||||||
|
request.AddHeader("content-type", "application/x-www-form-urlencoded");
|
||||||
|
RestResponse endpoint_checks = client.ExecutePostAsync(request).Result;
|
||||||
|
if (endpoint_checks.StatusCode != System.Net.HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
return Failure("HTTP status code: " + endpoint_checks.StatusCode.ToString(), "FetchNextNotecard", new [] { endpoint, endpointcode });
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
NotecardEndpoint server_reply = JsonConvert.DeserializeObject<NotecardEndpoint>(endpoint_checks.Content);
|
||||||
|
if (server_reply.status == false)
|
||||||
|
{
|
||||||
|
return Failure("Bad reply: " + server_reply.message, "FetchNextNotecard", new [] { endpoint, endpointcode });
|
||||||
|
}
|
||||||
|
if (server_reply.NotecardTitle.Length < 3)
|
||||||
|
{
|
||||||
|
return Failure("Notecard title is to short", "FetchNextNotecard", new [] { endpoint, endpointcode });
|
||||||
|
}
|
||||||
|
return BasicReply
|
||||||
|
(
|
||||||
|
bot.SendNotecard(server_reply.NotecardTitle,
|
||||||
|
server_reply.NotecardContent,
|
||||||
|
(UUID)server_reply.AvatarUUID).ToString(),
|
||||||
|
"FetchNextNotecard",
|
||||||
|
new [] { endpoint, endpointcode }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return Failure("Error: " + e.Message + "", "FetchNextNotecard", new [] { endpoint, endpointcode });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NotecardEndpoint : BasicEndpoint
|
||||||
|
{
|
||||||
|
public string AvatarUUID { get; set; }
|
||||||
|
public string NotecardTitle { get; set; }
|
||||||
|
public string NotecardContent { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BasicEndpoint
|
||||||
|
{
|
||||||
|
public bool status { get; set; }
|
||||||
|
public string message { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
SecondBotEvents/Config/BasicConfig.cs
Normal file
50
SecondBotEvents/Config/BasicConfig.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Config
|
||||||
|
{
|
||||||
|
public class BasicConfig : Config
|
||||||
|
{
|
||||||
|
public BasicConfig(bool fromENV, string fromFolder = "") : base(fromENV, fromFolder) { }
|
||||||
|
protected override void MakeSettings()
|
||||||
|
{
|
||||||
|
filename = "basic";
|
||||||
|
settings.Add("username");
|
||||||
|
settings.Add("password");
|
||||||
|
settings.Add("loginURI");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetUsername()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("username","Firstname Lastname");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetPassword()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("password", "passwordHere");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetFirstName()
|
||||||
|
{
|
||||||
|
|
||||||
|
string[] bits = ReadSettingAsString("username", "Firstname Lastname").Split(" ");
|
||||||
|
return bits[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetLastName()
|
||||||
|
{
|
||||||
|
string[] bits = ReadSettingAsString("username", "Firstname Lastname").Split(" ");
|
||||||
|
if(bits.Length == 2)
|
||||||
|
{
|
||||||
|
return bits[1];
|
||||||
|
}
|
||||||
|
return "Resident";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetLoginURI()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("loginURI", "secondlife");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
SecondBotEvents/Config/CommandsConfig.cs
Normal file
58
SecondBotEvents/Config/CommandsConfig.cs
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Config
|
||||||
|
{
|
||||||
|
public class CommandsConfig : Config
|
||||||
|
{
|
||||||
|
public CommandsConfig(bool fromENV, string fromFolder = "") : base(fromENV, fromFolder) { }
|
||||||
|
protected override void MakeSettings()
|
||||||
|
{
|
||||||
|
filename = "commands";
|
||||||
|
settings.Add("allowFundsCommands");
|
||||||
|
settings.Add("allowIMcontrol");
|
||||||
|
settings.Add("sharedSecret");
|
||||||
|
settings.Add("onlySelectedAvs");
|
||||||
|
settings.Add("avsCSV");
|
||||||
|
settings.Add("enforceTimeWindow");
|
||||||
|
settings.Add("timeWindowSecs");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetEnforceTimeWindow()
|
||||||
|
{
|
||||||
|
return ReadSettingAsBool("enforceTimeWindow", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetTimeWindowSecs()
|
||||||
|
{
|
||||||
|
return ReadSettingAsInt("timeWindowSecs", 35);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetOnlySelectedAvs()
|
||||||
|
{
|
||||||
|
return ReadSettingAsBool("onlySelectedAvs", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> GetAvsCSV()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("avsCSV", "Madpeter Zond,Madpeter Zond,Madpeter Zond").Split(",").ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetAllowFundsCommands()
|
||||||
|
{
|
||||||
|
return ReadSettingAsBool("allowFundsCommands", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetAllowIMcontrol()
|
||||||
|
{
|
||||||
|
return ReadSettingAsBool("allowIMcontrol", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetSharedSecret()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("sharedSecret", "ThisIsMySecret");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
SecondBotEvents/Config/HttpConfig.cs
Normal file
28
SecondBotEvents/Config/HttpConfig.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Config
|
||||||
|
{
|
||||||
|
public class HttpConfig: Config
|
||||||
|
{
|
||||||
|
public HttpConfig(bool fromENV, string fromFolder = "") : base(fromENV, fromFolder) { }
|
||||||
|
protected override void MakeSettings()
|
||||||
|
{
|
||||||
|
filename = "http";
|
||||||
|
settings.Add("enabled");
|
||||||
|
settings.Add("host");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetHost()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("host", "http://*:80");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetEnabled()
|
||||||
|
{
|
||||||
|
return ReadSettingAsBool("enabled", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace SecondBotEvents.Config
|
|
||||||
{
|
|
||||||
public class basic_config : config
|
|
||||||
{
|
|
||||||
public basic_config(bool fromENV, string fromFolder = "") : base(fromENV, fromFolder) { }
|
|
||||||
protected override void makeSettings()
|
|
||||||
{
|
|
||||||
filename = "basic";
|
|
||||||
settings.Add("username");
|
|
||||||
settings.Add("password");
|
|
||||||
settings.Add("loginURI");
|
|
||||||
}
|
|
||||||
|
|
||||||
public string getUsername()
|
|
||||||
{
|
|
||||||
return readSetting("username","Firstname Lastname");
|
|
||||||
}
|
|
||||||
|
|
||||||
public string getPassword()
|
|
||||||
{
|
|
||||||
return readSetting("password", "passwordHere");
|
|
||||||
}
|
|
||||||
|
|
||||||
public string getFirstName()
|
|
||||||
{
|
|
||||||
|
|
||||||
string[] bits = readSetting("username", "Firstname Lastname").Split(" ");
|
|
||||||
return bits[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public string getLastName()
|
|
||||||
{
|
|
||||||
string[] bits = readSetting("username", "Firstname Lastname").Split(" ");
|
|
||||||
if(bits.Length == 2)
|
|
||||||
{
|
|
||||||
return bits[1];
|
|
||||||
}
|
|
||||||
return "Resident";
|
|
||||||
}
|
|
||||||
|
|
||||||
public string getLoginURI()
|
|
||||||
{
|
|
||||||
return readSetting("loginURI", "secondlife");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -8,40 +8,40 @@ using System.Text;
|
||||||
|
|
||||||
namespace SecondBotEvents.Config
|
namespace SecondBotEvents.Config
|
||||||
{
|
{
|
||||||
public abstract class config
|
public abstract class Config
|
||||||
{
|
{
|
||||||
protected Dictionary<string, string> mysettings = new Dictionary<string, string>();
|
protected Dictionary<string, string> mysettings = new Dictionary<string, string>();
|
||||||
protected List<string> settings = new List<string>();
|
protected List<string> settings = new List<string>();
|
||||||
protected string filename = "config";
|
protected string filename = "config";
|
||||||
protected bool loaded = false;
|
protected bool loaded = false;
|
||||||
public config(bool fromENV, string fromFolder="")
|
public Config(bool fromENV, string fromFolder="")
|
||||||
{
|
{
|
||||||
makeSettings();
|
MakeSettings();
|
||||||
loadSettings(fromENV, fromFolder);
|
LoadSettings(fromENV, fromFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool isLoaded()
|
public bool IsLoaded()
|
||||||
{
|
{
|
||||||
return loaded;
|
return loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void loadSettings(bool fromENV, string fromFolder = "")
|
protected void LoadSettings(bool fromENV, string fromFolder = "")
|
||||||
{
|
{
|
||||||
if(fromENV == true)
|
if(fromENV == true)
|
||||||
{
|
{
|
||||||
loadSettingsFromEnv();
|
LoadSettingsFromEnv();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loadSettingsFromFile(fromFolder);
|
LoadSettingsFromFile(fromFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void makeSettingsFile(string fromFolder)
|
protected void MakeSettingsFile(string fromFolder)
|
||||||
{
|
{
|
||||||
Dictionary<string, string> saveMe = new Dictionary<string, string>();
|
Dictionary<string, string> saveMe = new Dictionary<string, string>();
|
||||||
Type thisType = this.GetType();
|
Type thisType = this.GetType();
|
||||||
foreach (string setting in settings)
|
foreach (string setting in settings)
|
||||||
{
|
{
|
||||||
string reader = "get"+ StringExtensions.FirstCharToUpper(setting);
|
string reader = "Get"+ StringExtensions.FirstCharToUpper(setting);
|
||||||
MethodInfo theMethod = thisType.GetMethod(reader);
|
MethodInfo theMethod = thisType.GetMethod(reader);
|
||||||
string value = theMethod.Invoke(this, null).ToString();
|
string value = theMethod.Invoke(this, null).ToString();
|
||||||
saveMe.Add(setting, value);
|
saveMe.Add(setting, value);
|
||||||
|
|
@ -52,14 +52,14 @@ namespace SecondBotEvents.Config
|
||||||
IO.WriteFile(writeFile, JsonConvert.SerializeObject(saveMe));
|
IO.WriteFile(writeFile, JsonConvert.SerializeObject(saveMe));
|
||||||
|
|
||||||
}
|
}
|
||||||
protected void loadSettingsFromFile(string fromFolder)
|
protected void LoadSettingsFromFile(string fromFolder)
|
||||||
{
|
{
|
||||||
SimpleIO IO = new SimpleIO();
|
SimpleIO IO = new SimpleIO();
|
||||||
IO.ChangeRoot(fromFolder);
|
IO.ChangeRoot(fromFolder);
|
||||||
string readfile = filename + ".json";
|
string readfile = filename + ".json";
|
||||||
if (IO.Exists(readfile) == false)
|
if (IO.Exists(readfile) == false)
|
||||||
{
|
{
|
||||||
makeSettingsFile(fromFolder);
|
MakeSettingsFile(fromFolder);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JObject result = JObject.Parse(IO.ReadFile(readfile));
|
JObject result = JObject.Parse(IO.ReadFile(readfile));
|
||||||
|
|
@ -80,7 +80,7 @@ namespace SecondBotEvents.Config
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void loadSettingsFromEnv()
|
protected void LoadSettingsFromEnv()
|
||||||
{
|
{
|
||||||
foreach (string setting in settings)
|
foreach (string setting in settings)
|
||||||
{
|
{
|
||||||
|
|
@ -96,12 +96,12 @@ namespace SecondBotEvents.Config
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void makeSettings()
|
protected virtual void MakeSettings()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string readSetting(string key, string defaultValue)
|
protected string ReadSettingAsString(string key, string defaultValue)
|
||||||
{
|
{
|
||||||
if (mysettings.ContainsKey(key) == false)
|
if (mysettings.ContainsKey(key) == false)
|
||||||
{
|
{
|
||||||
|
|
@ -109,5 +109,25 @@ namespace SecondBotEvents.Config
|
||||||
}
|
}
|
||||||
return mysettings[key];
|
return mysettings[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected bool ReadSettingAsBool(string key,bool defaultValue=false)
|
||||||
|
{
|
||||||
|
bool result = bool.TryParse(ReadSettingAsString(key, defaultValue.ToString()), out bool enabled);
|
||||||
|
if (result == false)
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int ReadSettingAsInt(string key, int defaultValue = 30)
|
||||||
|
{
|
||||||
|
bool result = int.TryParse(ReadSettingAsString(key, defaultValue.ToString()), out int value);
|
||||||
|
if (result == false)
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace SecondBotEvents.Config
|
|
||||||
{
|
|
||||||
public class http_config: config
|
|
||||||
{
|
|
||||||
public http_config(bool fromENV, string fromFolder = "") : base(fromENV, fromFolder) { }
|
|
||||||
protected override void makeSettings()
|
|
||||||
{
|
|
||||||
filename = "http";
|
|
||||||
settings.Add("enabled");
|
|
||||||
settings.Add("host");
|
|
||||||
}
|
|
||||||
|
|
||||||
public string getHost()
|
|
||||||
{
|
|
||||||
return readSetting("host", "http://*:80");
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool getEnabled()
|
|
||||||
{
|
|
||||||
bool result = bool.TryParse(readSetting("enabled", "false"), out bool enabled);
|
|
||||||
if (result == false)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -13,21 +13,22 @@ namespace SecondBotEvents
|
||||||
Console.WriteLine("Welcome to Secondbot [Events build] version: " + AssemblyInfo.GetGitHash());
|
Console.WriteLine("Welcome to Secondbot [Events build] version: " + AssemblyInfo.GetGitHash());
|
||||||
EventsSecondBot worker = new EventsSecondBot(args);
|
EventsSecondBot worker = new EventsSecondBot(args);
|
||||||
|
|
||||||
while(worker.exit() == false)
|
while(worker.Exit() == false)
|
||||||
{
|
{
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class EventsSecondBot
|
public class EventsSecondBot
|
||||||
{
|
{
|
||||||
public http HttpService = null;
|
public HttpService HttpService = null;
|
||||||
public BotClient botClient = null;
|
public CommandsService CommandsService = null;
|
||||||
|
public BotClientService botClient = null;
|
||||||
|
|
||||||
|
|
||||||
private EventHandler<botClientNotice> botclient_eventNotices;
|
private EventHandler<BotClientNotice> botclient_eventNotices;
|
||||||
public event EventHandler<botClientNotice> botClientNoticeEvent
|
public event EventHandler<BotClientNotice> BotClientNoticeEvent
|
||||||
{
|
{
|
||||||
add { lock (botclient_event_attach) { botclient_eventNotices += value; } }
|
add { lock (botclient_event_attach) { botclient_eventNotices += value; } }
|
||||||
remove { lock (botclient_event_attach) { botclient_eventNotices -= value; } }
|
remove { lock (botclient_event_attach) { botclient_eventNotices -= value; } }
|
||||||
|
|
@ -35,13 +36,13 @@ namespace SecondBotEvents
|
||||||
|
|
||||||
private readonly object botclient_event_attach = new object();
|
private readonly object botclient_event_attach = new object();
|
||||||
|
|
||||||
public void triggerBotClientEvent(bool asRestart)
|
public void TriggerBotClientEvent(bool asRestart)
|
||||||
{
|
{
|
||||||
EventHandler<botClientNotice> handler = botclient_eventNotices;
|
EventHandler<BotClientNotice> handler = botclient_eventNotices;
|
||||||
handler?.Invoke(this, new botClientNotice(asRestart));
|
handler?.Invoke(this, new BotClientNotice(asRestart));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string getVersion()
|
public string GetVersion()
|
||||||
{
|
{
|
||||||
return AssemblyInfo.GetGitHash();
|
return AssemblyInfo.GetGitHash();
|
||||||
}
|
}
|
||||||
|
|
@ -60,43 +61,45 @@ namespace SecondBotEvents
|
||||||
{
|
{
|
||||||
fromFolder = args[0];
|
fromFolder = args[0];
|
||||||
}
|
}
|
||||||
restartServices();
|
RestartServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restartServices()
|
public void RestartServices()
|
||||||
{
|
{
|
||||||
stopServices();
|
StopServices();
|
||||||
startServices();
|
StartServices();
|
||||||
}
|
}
|
||||||
protected void startServices()
|
protected void StartServices()
|
||||||
{
|
{
|
||||||
HttpService = new http(this);
|
botClient = new BotClientService(this);
|
||||||
HttpService.start();
|
HttpService = new HttpService(this);
|
||||||
botClient = new BotClient(this);
|
CommandsService = new CommandsService(this);
|
||||||
if(botClient.basicCfg.isLoaded() == false)
|
if (botClient.IsLoaded() == false)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Config is not loaded :(");
|
Console.WriteLine("Config is not loaded :(");
|
||||||
exitNow = true;
|
exitNow = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
botClient.start();
|
HttpService.Start();
|
||||||
|
CommandsService.Start();
|
||||||
|
botClient.Start();
|
||||||
|
|
||||||
}
|
}
|
||||||
protected void stopServices()
|
protected void StopServices()
|
||||||
{
|
{
|
||||||
if (HttpService != null)
|
if (HttpService != null)
|
||||||
{
|
{
|
||||||
HttpService.stop();
|
HttpService.Stop();
|
||||||
}
|
}
|
||||||
if(botClient != null)
|
if(botClient != null)
|
||||||
{
|
{
|
||||||
botClient.stop();
|
botClient.Stop();
|
||||||
}
|
}
|
||||||
HttpService = null;
|
HttpService = null;
|
||||||
botClient = null;
|
botClient = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool exit()
|
public bool Exit()
|
||||||
{
|
{
|
||||||
return exitNow;
|
return exitNow;
|
||||||
}
|
}
|
||||||
|
|
@ -115,10 +118,10 @@ namespace SecondBotEvents
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class botClientNotice
|
public class BotClientNotice
|
||||||
{
|
{
|
||||||
public bool isRestart = false;
|
public bool isRestart = false;
|
||||||
public botClientNotice(bool asRestart=false)
|
public BotClientNotice(bool asRestart=false)
|
||||||
{
|
{
|
||||||
isRestart = asRestart;
|
isRestart = asRestart;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
|
<PackageReference Include="RestSharp" Version="107.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
using OpenMetaverse;
|
|
||||||
using SecondBotEvents.Config;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace SecondBotEvents.Services
|
|
||||||
{
|
|
||||||
internal class BotClient : service
|
|
||||||
{
|
|
||||||
public GridClient client = null;
|
|
||||||
public basic_config basicCfg = null;
|
|
||||||
public BotClient(EventsSecondBot setMaster) : base(setMaster)
|
|
||||||
{
|
|
||||||
basicCfg = new basic_config(master.fromEnv, master.fromFolder);
|
|
||||||
}
|
|
||||||
public override void start()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Client service [Starting]");
|
|
||||||
login();
|
|
||||||
}
|
|
||||||
public override void stop()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Client service [Stopping]");
|
|
||||||
resetClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void botLoggedOut(object o, LoggedOutEventArgs e)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Client service ~ Logged out");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void botLoggedIn(object o, SimConnectedEventArgs e)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Client service ~ Connected to sim: "+e.Simulator.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void botLoseSim(object o, SimDisconnectedEventArgs e)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Client service ~ Disconnected from sim: " + e.Simulator.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void botDisconnected(object o, DisconnectedEventArgs e)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Client service ~ Network lost: " + e.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void botLoginStatus(object o, LoginProgressEventArgs e)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Client service ~ Login status: " + e.Status.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void resetClient()
|
|
||||||
{
|
|
||||||
bool isRestart = false;
|
|
||||||
if (client != null)
|
|
||||||
{
|
|
||||||
client.Network.Logout();
|
|
||||||
isRestart = true;
|
|
||||||
}
|
|
||||||
client = null;
|
|
||||||
client = new GridClient();
|
|
||||||
master.triggerBotClientEvent(isRestart);
|
|
||||||
client.Network.SimConnected += botLoggedIn;
|
|
||||||
client.Network.LoggedOut += botLoggedOut;
|
|
||||||
client.Network.Disconnected += botDisconnected;
|
|
||||||
client.Network.SimDisconnected += botLoseSim;
|
|
||||||
client.Network.LoginProgress += botLoginStatus;
|
|
||||||
}
|
|
||||||
public void login()
|
|
||||||
{
|
|
||||||
resetClient();
|
|
||||||
LoginParams loginParams = new LoginParams(
|
|
||||||
client,
|
|
||||||
basicCfg.getFirstName(),
|
|
||||||
basicCfg.getLastName(),
|
|
||||||
basicCfg.getPassword(),
|
|
||||||
"secondbot",
|
|
||||||
master.getVersion()
|
|
||||||
);
|
|
||||||
if (basicCfg.getLoginURI() != "secondlife")
|
|
||||||
{
|
|
||||||
loginParams.URI = basicCfg.getLoginURI();
|
|
||||||
}
|
|
||||||
client.Network.BeginLogin(loginParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
96
SecondBotEvents/Services/BotClientService.cs
Normal file
96
SecondBotEvents/Services/BotClientService.cs
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Config;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Services
|
||||||
|
{
|
||||||
|
public class BotClientService : Services
|
||||||
|
{
|
||||||
|
public GridClient client = null;
|
||||||
|
protected BasicConfig basicCfg = null;
|
||||||
|
public BotClientService(EventsSecondBot setMaster) : base(setMaster)
|
||||||
|
{
|
||||||
|
basicCfg = new BasicConfig(master.fromEnv, master.fromFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsLoaded()
|
||||||
|
{
|
||||||
|
return basicCfg.IsLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Start()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Client service [Starting]");
|
||||||
|
Login();
|
||||||
|
}
|
||||||
|
public override void Stop()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Client service [Stopping]");
|
||||||
|
ResetClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotLoggedOut(object o, LoggedOutEventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Client service ~ Logged out");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotSimConnected(object o, SimConnectedEventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Client service ~ Connected to sim: "+e.Simulator.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotSimDisconnected(object o, SimDisconnectedEventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Client service ~ Disconnected from sim: " + e.Simulator.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotDisconnected(object o, DisconnectedEventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Client service ~ Network disconnected: " + e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotLoginStatus(object o, LoginProgressEventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Client service ~ Login status: " + e.Status.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ResetClient()
|
||||||
|
{
|
||||||
|
bool isRestart = false;
|
||||||
|
if (client != null)
|
||||||
|
{
|
||||||
|
client.Network.Logout();
|
||||||
|
isRestart = true;
|
||||||
|
}
|
||||||
|
client = null;
|
||||||
|
client = new GridClient();
|
||||||
|
master.TriggerBotClientEvent(isRestart);
|
||||||
|
client.Network.SimConnected += BotSimConnected;
|
||||||
|
client.Network.LoggedOut += BotLoggedOut;
|
||||||
|
client.Network.Disconnected += BotDisconnected;
|
||||||
|
client.Network.SimDisconnected += BotSimDisconnected;
|
||||||
|
client.Network.LoginProgress += BotLoginStatus;
|
||||||
|
}
|
||||||
|
public void Login()
|
||||||
|
{
|
||||||
|
ResetClient();
|
||||||
|
LoginParams loginParams = new LoginParams(
|
||||||
|
client,
|
||||||
|
basicCfg.GetFirstName(),
|
||||||
|
basicCfg.GetLastName(),
|
||||||
|
basicCfg.GetPassword(),
|
||||||
|
"secondbot",
|
||||||
|
master.GetVersion()
|
||||||
|
);
|
||||||
|
if (basicCfg.GetLoginURI() != "secondlife")
|
||||||
|
{
|
||||||
|
loginParams.URI = basicCfg.GetLoginURI();
|
||||||
|
}
|
||||||
|
client.Network.BeginLogin(loginParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
149
SecondBotEvents/Services/Commands.cs
Normal file
149
SecondBotEvents/Services/Commands.cs
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Config;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Services
|
||||||
|
{
|
||||||
|
public class CommandsService : Services
|
||||||
|
{
|
||||||
|
public CommandsConfig myConfig = null;
|
||||||
|
public bool acceptNewCommands = false;
|
||||||
|
public CommandsService(EventsSecondBot setMaster) : base(setMaster)
|
||||||
|
{
|
||||||
|
myConfig = new CommandsConfig(master.fromEnv, master.fromFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string,int> acceptTokens = new Dictionary<string,int>();
|
||||||
|
public bool AllowToken(string token)
|
||||||
|
{
|
||||||
|
if(acceptTokens.ContainsKey(token) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (acceptTokens[token] != -1)
|
||||||
|
{
|
||||||
|
acceptTokens[token] = acceptTokens[token] - 1;
|
||||||
|
if(acceptTokens[token] == 0)
|
||||||
|
{
|
||||||
|
acceptTokens.Remove(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string SingleUseToken()
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
string token = "";
|
||||||
|
while(found == false)
|
||||||
|
{
|
||||||
|
token = SecondbotHelpers.GetSHA1(token + SecondbotHelpers.UnixTimeNow().ToString());
|
||||||
|
if(acceptTokens.ContainsKey(token) == false)
|
||||||
|
{
|
||||||
|
addNewToken(token, 1);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addNewToken(string token,int uses)
|
||||||
|
{
|
||||||
|
if (acceptTokens.ContainsKey(token) == false)
|
||||||
|
{
|
||||||
|
acceptTokens[token] = 0;
|
||||||
|
}
|
||||||
|
acceptTokens[token] = uses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Start()
|
||||||
|
{
|
||||||
|
master.BotClientNoticeEvent += BotClientRestart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Stop()
|
||||||
|
{
|
||||||
|
acceptNewCommands = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotClientRestart(object o, BotClientNotice e)
|
||||||
|
{
|
||||||
|
acceptNewCommands = false;
|
||||||
|
Console.WriteLine("Commands service [Attached to new client]");
|
||||||
|
master.botClient.client.Network.LoggedOut += BotLoggedOut;
|
||||||
|
master.botClient.client.Network.SimConnected += BotLoggedIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotLoggedOut(object o, LoggedOutEventArgs e)
|
||||||
|
{
|
||||||
|
master.botClient.client.Network.SimConnected += BotLoggedIn;
|
||||||
|
Console.WriteLine("Commands service [Waiting for connect]");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotImMessage(object o, InstantMessageEventArgs e)
|
||||||
|
{
|
||||||
|
if(acceptNewCommands == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.IM.FromAgentName == master.botClient.client.Self.Name)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (myConfig.GetAllowIMcontrol() == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool acceptMessage = true;
|
||||||
|
bool requireSigning = false;
|
||||||
|
switch (e.IM.Dialog)
|
||||||
|
{
|
||||||
|
case InstantMessageDialog.MessageFromObject:
|
||||||
|
{
|
||||||
|
requireSigning = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case InstantMessageDialog.MessageFromAgent: // shared with SessionSend
|
||||||
|
case InstantMessageDialog.SessionSend:
|
||||||
|
{
|
||||||
|
if(myConfig.GetOnlySelectedAvs() == false)
|
||||||
|
{
|
||||||
|
acceptMessage = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
acceptMessage = myConfig.GetAvsCSV().Contains(e.IM.FromAgentName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
acceptMessage = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (requireSigning == true)
|
||||||
|
{
|
||||||
|
acceptMessage = acceptMessageSigned(e.IM.Message);
|
||||||
|
}
|
||||||
|
if (acceptMessage == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool acceptMessageSigned(string message)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotLoggedIn(object o, SimConnectedEventArgs e)
|
||||||
|
{
|
||||||
|
master.botClient.client.Network.SimConnected -= BotLoggedIn;
|
||||||
|
master.botClient.client.Self.IM += BotImMessage;
|
||||||
|
acceptNewCommands = true;
|
||||||
|
Console.WriteLine("Commands service [accepting IM commands]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
300
SecondBotEvents/Services/HttpService.cs
Normal file
300
SecondBotEvents/Services/HttpService.cs
Normal file
|
|
@ -0,0 +1,300 @@
|
||||||
|
using EmbedIO;
|
||||||
|
using EmbedIO.Actions;
|
||||||
|
using EmbedIO.WebApi;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using SecondBotEvents.Config;
|
||||||
|
using Swan.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Services
|
||||||
|
{
|
||||||
|
public class HttpService: Services
|
||||||
|
{
|
||||||
|
protected WebServer HTTPendpoint = null;
|
||||||
|
protected HttpConfig myConfig;
|
||||||
|
protected bool acceptBotCommands = false;
|
||||||
|
public HttpService(EventsSecondBot setMaster) : base(setMaster)
|
||||||
|
{
|
||||||
|
myConfig = new HttpConfig(master.fromEnv,master.fromFolder);
|
||||||
|
if (myConfig.GetEnabled() == false)
|
||||||
|
{
|
||||||
|
Console.WriteLine(Status());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Status()
|
||||||
|
{
|
||||||
|
if(myConfig == null)
|
||||||
|
{
|
||||||
|
return "HTTP service [Config status broken]";
|
||||||
|
}
|
||||||
|
if (myConfig.GetEnabled() == false)
|
||||||
|
{
|
||||||
|
return "HTTP service [- Not requested -]";
|
||||||
|
}
|
||||||
|
// @todo HTTP server check here
|
||||||
|
if(HTTPendpoint == null)
|
||||||
|
{
|
||||||
|
return "HTTP endpoint not online";
|
||||||
|
}
|
||||||
|
if (acceptBotCommands == false)
|
||||||
|
{
|
||||||
|
return "Active [Service]";
|
||||||
|
}
|
||||||
|
return "Active [Commands]";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotClientRestart(object o, BotClientNotice e)
|
||||||
|
{
|
||||||
|
acceptBotCommands = false;
|
||||||
|
Console.WriteLine("HTTP service [Attached to new client]");
|
||||||
|
master.botClient.client.Network.LoggedOut += BotLoggedOut;
|
||||||
|
master.botClient.client.Network.SimConnected += BotLoggedIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotLoggedOut(object o, LoggedOutEventArgs e)
|
||||||
|
{
|
||||||
|
acceptBotCommands = false;
|
||||||
|
master.botClient.client.Network.SimConnected += BotLoggedIn;
|
||||||
|
Console.WriteLine("HTTP service [Bot commands disabled]");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotLoggedIn(object o, SimConnectedEventArgs e)
|
||||||
|
{
|
||||||
|
master.botClient.client.Network.SimConnected -= BotLoggedIn;
|
||||||
|
acceptBotCommands = true;
|
||||||
|
Console.WriteLine("HTTP service [Bot commands enabled]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Start()
|
||||||
|
{
|
||||||
|
if (myConfig.GetEnabled() == false)
|
||||||
|
{
|
||||||
|
Console.WriteLine("HTTP service [Disabled]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Stop();
|
||||||
|
master.BotClientNoticeEvent += BotClientRestart;
|
||||||
|
Console.WriteLine("HTTP service [Enabled]");
|
||||||
|
CreateWebServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Stop()
|
||||||
|
{
|
||||||
|
if (myConfig.GetEnabled() == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
master.BotClientNoticeEvent -= BotClientRestart;
|
||||||
|
if (HTTPendpoint != null)
|
||||||
|
{
|
||||||
|
HTTPendpoint.Dispose();
|
||||||
|
HTTPendpoint = null;
|
||||||
|
Console.WriteLine("HTTP service [Stopping]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateWebServer()
|
||||||
|
{
|
||||||
|
Swan.Logging.Logger.UnregisterLogger<ConsoleLogger>();
|
||||||
|
HTTPendpoint = new WebServer(o => o
|
||||||
|
.WithUrlPrefix(myConfig.GetHost())
|
||||||
|
.WithMode(HttpListenerMode.EmbedIO))
|
||||||
|
.WithCors()
|
||||||
|
.WithModule(new ActionModule("/", HttpVerbs.Any, ctx => ctx.SendDataAsync(new { Message = "Error" }))
|
||||||
|
);
|
||||||
|
HTTPendpoint.RunAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class CommandsAPI : WebApiController
|
||||||
|
{
|
||||||
|
protected EventsSecondBot master;
|
||||||
|
public CommandsAPI(EventsSecondBot setmaster)
|
||||||
|
{
|
||||||
|
master = setmaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool AllowToken(string token)
|
||||||
|
{
|
||||||
|
return master.CommandsService.AllowToken(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected UUID avataruuid = UUID.Zero;
|
||||||
|
protected Parcel targetparcel = null;
|
||||||
|
|
||||||
|
protected bool disableIPchecks = false;
|
||||||
|
public void disableIPlockout()
|
||||||
|
{
|
||||||
|
disableIPchecks = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPAddress handleGetClientIP()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (disableIPchecks == true)
|
||||||
|
{
|
||||||
|
return IPAddress.Parse("127.0.0.1");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return HttpContext.Request.RemoteEndPoint.Address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error getting client ip");
|
||||||
|
return IPAddress.Parse("0.0.0.0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GridClient getClient()
|
||||||
|
{
|
||||||
|
return master.botClient.client;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected KeyValuePair<bool, string> SetupCurrentParcel()
|
||||||
|
{
|
||||||
|
if (getClient().Network.CurrentSim == null)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<bool, string>(false, "Error not in a sim");
|
||||||
|
}
|
||||||
|
int localid = getClient().Parcels.GetParcelLocalID(getClient().Network.CurrentSim, getClient().Self.SimPosition);
|
||||||
|
if (getClient().Network.CurrentSim.Parcels.ContainsKey(localid) == false)
|
||||||
|
{
|
||||||
|
Thread.Sleep(2000);
|
||||||
|
localid = getClient().Parcels.GetParcelLocalID(getClient().Network.CurrentSim, getClient().Self.SimPosition);
|
||||||
|
if (getClient().Network.CurrentSim.Parcels.ContainsKey(localid) == false)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<bool, string>(false, "Parcel data not ready");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
targetparcel = getClient().Network.CurrentSim.Parcels[localid];
|
||||||
|
return new KeyValuePair<bool, string>(true, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ProcessAvatar(string avatar)
|
||||||
|
{
|
||||||
|
string[] bits = avatar.Split(' ');
|
||||||
|
avataruuid = UUID.Zero;
|
||||||
|
// @todo Avatar storage system
|
||||||
|
UUID.TryParse(avatar, out avataruuid);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SuccessNoReturn(string command)
|
||||||
|
{
|
||||||
|
SuccessNoReturn(command, new string[] { });
|
||||||
|
}
|
||||||
|
protected void SuccessNoReturn(string command, string[] args)
|
||||||
|
{
|
||||||
|
// @todo Command history storage system
|
||||||
|
}
|
||||||
|
|
||||||
|
protected object BasicReply(string input, string command)
|
||||||
|
{
|
||||||
|
return BasicReply(input, command, new string[] { });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected object BasicReply(string input)
|
||||||
|
{
|
||||||
|
return BasicReply(input, getCallingCommand(), new string[] { });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected object BasicReply(string input, string command, string[] args)
|
||||||
|
{
|
||||||
|
// @todo Command history storage system
|
||||||
|
return new { reply = input, status = true };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected object Failure(string input, string command, string[] args)
|
||||||
|
{
|
||||||
|
// @todo Command history storage system
|
||||||
|
return new { reply = input, status = false };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected object Failure(string input)
|
||||||
|
{
|
||||||
|
// @todo Command history storage system
|
||||||
|
return new { reply = input, command= getCallingCommand(), status = false };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string getCallingCommand()
|
||||||
|
{
|
||||||
|
return (new System.Diagnostics.StackTrace()).GetFrame(2).GetMethod().Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected object Failure(string input, string command, string[] args, string whyfailed)
|
||||||
|
{
|
||||||
|
// @todo Command history storage system
|
||||||
|
return new { reply = input, status = false };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected object Failure(string input, string command)
|
||||||
|
{
|
||||||
|
return Failure(input, command, new string[] { });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
|
public class About : Attribute
|
||||||
|
{
|
||||||
|
public string about = "";
|
||||||
|
public About(string about)
|
||||||
|
{
|
||||||
|
this.about = about;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
|
public class NeedsToken : Attribute
|
||||||
|
{
|
||||||
|
public bool needsToken = true;
|
||||||
|
public NeedsToken(bool needsToken)
|
||||||
|
{
|
||||||
|
this.needsToken = needsToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
|
||||||
|
public class ReturnHints : Attribute
|
||||||
|
{
|
||||||
|
public string hint = "";
|
||||||
|
public bool good = true;
|
||||||
|
public ReturnHints(string hint)
|
||||||
|
{
|
||||||
|
this.hint = hint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
|
||||||
|
public class ReturnHintsFailure : ReturnHints
|
||||||
|
{
|
||||||
|
public ReturnHintsFailure(string hint): base(hint)
|
||||||
|
{
|
||||||
|
this.good = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
|
||||||
|
public class ArgHints : Attribute
|
||||||
|
{
|
||||||
|
public string name = "";
|
||||||
|
public string typename = "";
|
||||||
|
public string about = "";
|
||||||
|
|
||||||
|
public ArgHints(string name,string typename, string about)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.typename = typename;
|
||||||
|
this.about = about;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
SecondBotEvents/Services/Services.cs
Normal file
34
SecondBotEvents/Services/Services.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Services
|
||||||
|
{
|
||||||
|
public abstract class Services
|
||||||
|
{
|
||||||
|
public EventsSecondBot master;
|
||||||
|
public Services(EventsSecondBot setMaster)
|
||||||
|
{
|
||||||
|
master = setMaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string Status()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Start()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public virtual void Stop()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public void Restart()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Actions;
|
|
||||||
using OpenMetaverse;
|
|
||||||
using SecondBotEvents.Config;
|
|
||||||
using Swan.Logging;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace SecondBotEvents.Services
|
|
||||||
{
|
|
||||||
internal class http: service
|
|
||||||
{
|
|
||||||
protected WebServer HTTPendpoint = null;
|
|
||||||
protected http_config myConfig;
|
|
||||||
protected bool acceptBotCommands = false;
|
|
||||||
public http(EventsSecondBot setMaster) : base(setMaster)
|
|
||||||
{
|
|
||||||
myConfig = new http_config(master.fromEnv,master.fromFolder);
|
|
||||||
if (myConfig.getEnabled() == false)
|
|
||||||
{
|
|
||||||
Console.WriteLine(status());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
master.botClientNoticeEvent += botClientRestart;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string status()
|
|
||||||
{
|
|
||||||
if(myConfig == null)
|
|
||||||
{
|
|
||||||
return "HTTP service [Config status broken]";
|
|
||||||
}
|
|
||||||
if (myConfig.getEnabled() == false)
|
|
||||||
{
|
|
||||||
return "HTTP service [- Not requested -]";
|
|
||||||
}
|
|
||||||
// @todo HTTP server check here
|
|
||||||
if(HTTPendpoint == null)
|
|
||||||
{
|
|
||||||
return "HTTP endpoint not online";
|
|
||||||
}
|
|
||||||
if (acceptBotCommands == false)
|
|
||||||
{
|
|
||||||
return "Active [Service]";
|
|
||||||
}
|
|
||||||
return "Active [Commands]";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void botClientRestart(object o, botClientNotice e)
|
|
||||||
{
|
|
||||||
acceptBotCommands = false;
|
|
||||||
Console.WriteLine("HTTP service [Attached to new client]");
|
|
||||||
master.botClient.client.Network.LoggedOut += botLoggedOut;
|
|
||||||
master.botClient.client.Network.SimConnected += botLoggedIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void botLoggedOut(object o, LoggedOutEventArgs e)
|
|
||||||
{
|
|
||||||
acceptBotCommands = false;
|
|
||||||
master.botClient.client.Network.SimConnected += botLoggedIn;
|
|
||||||
Console.WriteLine("HTTP service [Bot commands disabled]");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void botLoggedIn(object o, SimConnectedEventArgs e)
|
|
||||||
{
|
|
||||||
master.botClient.client.Network.SimConnected -= botLoggedIn;
|
|
||||||
acceptBotCommands = true;
|
|
||||||
Console.WriteLine("HTTP service [Bot commands enabled]");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void start()
|
|
||||||
{
|
|
||||||
if (myConfig.getEnabled() == false)
|
|
||||||
{
|
|
||||||
Console.WriteLine("HTTP service [Disabled]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stop();
|
|
||||||
Console.WriteLine("HTTP service [Enabled]");
|
|
||||||
CreateWebServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void stop()
|
|
||||||
{
|
|
||||||
if (myConfig.getEnabled() == false)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(HTTPendpoint != null)
|
|
||||||
{
|
|
||||||
HTTPendpoint.Dispose();
|
|
||||||
HTTPendpoint = null;
|
|
||||||
Console.WriteLine("HTTP service [Stopping]");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateWebServer()
|
|
||||||
{
|
|
||||||
Swan.Logging.Logger.UnregisterLogger<ConsoleLogger>();
|
|
||||||
HTTPendpoint = new WebServer(o => o
|
|
||||||
.WithUrlPrefix(myConfig.getHost())
|
|
||||||
.WithMode(HttpListenerMode.EmbedIO))
|
|
||||||
.WithCors()
|
|
||||||
.WithModule(new ActionModule("/", HttpVerbs.Any, ctx => ctx.SendDataAsync(new { Message = "Error" }))
|
|
||||||
);
|
|
||||||
HTTPendpoint.RunAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace SecondBotEvents.Services
|
|
||||||
{
|
|
||||||
internal abstract class service
|
|
||||||
{
|
|
||||||
protected EventsSecondBot master;
|
|
||||||
public service(EventsSecondBot setMaster)
|
|
||||||
{
|
|
||||||
master = setMaster;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void start()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
public virtual void stop()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
public void restart()
|
|
||||||
{
|
|
||||||
stop();
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue