token mania!

This commit is contained in:
Madpeter 2022-03-17 21:08:02 +00:00
parent 4558b695f5
commit 50ff8f0c5f
33 changed files with 5363 additions and 408 deletions

View file

@ -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;
}
}

View 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");
}
}
}

View 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");
}
}
}

View 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 });
}
}
}

View 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; }
}
}

View 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 });
}
}
}

View 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
}
}

View 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 });
}
}
}

View 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 });
}
}
}

View 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 });
}
}
}

View 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; }
}
}

View 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>";
}
}

View 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 });
}
}
}

View 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;
}
}
}
}
}

View 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 });
}
}
}

View 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;
}
}

View 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 });
}
}
}

View 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; }
}
}
}

View 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");
}
}
}

View 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");
}
}
}

View 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);
}
}
}

View file

@ -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");
}
}
}

View file

@ -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;
}
} }
} }

View file

@ -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;
}
}
}

View file

@ -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;
} }

View file

@ -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>

View file

@ -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);
}
}
}

View 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);
}
}
}

View 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]");
}
}
}

View 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;
}
}
}

View 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();
}
}
}

View file

@ -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();
}
}
}

View file

@ -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();
}
}
}