using BetterSecondBotShared.API; using BetterSecondBotShared.IO; using BetterSecondBotShared.Json; using BetterSecondBotShared.logs; using BetterSecondBotShared.Static; using System; using System.Collections.Generic; using System.Reflection; using System.Text; namespace BetterSecondBot.WikiMake { class DebugModeCreateWiki { protected Dictionary> api_reports = new Dictionary>(); protected string html_header = ""; protected string html_footer = ""; protected string buildVersion = ""; protected SimpleIO io; protected Dictionary seen_command_names = new Dictionary(); public string CreateRoot() { StringBuilder sb = new StringBuilder(); sb.Append(html_header); sb.Append("

Build: "); sb.Append(buildVersion); sb.Append("


"); sb.Append(""); foreach (KeyValuePair> entry in api_reports) { sb.Append(""); sb.Append(""); sb.Append(""); } sb.Append("
InterfaceCommandsStatus
"); sb.Append(entry.Key); sb.Append(""); sb.Append(entry.Value.Key.ToString()); sb.Append(""); sb.Append(entry.Value.Value); sb.Append("
"); sb.Replace("[[AREA]]", "Home"); sb.Replace("[[SUBFOLDER]]", "files/"); sb.Replace("[[RETURNROOT]]", ""); sb = DebugModeCreateWiki.MenuActive(sb, "Home"); sb.Append(html_footer); return sb.ToString(); } protected static StringBuilder MenuActive(StringBuilder index, string area) { Dictionary active_swaps = new Dictionary { { "CoreActive", "" }, { "CLIActive", "" }, { "JSONActive", "" }, { "RLVapiActive", "" }, { "HTTPActive", "" } }; active_swaps["" + area + "Active"] = "Active"; foreach (KeyValuePair pair in active_swaps) { index = index.Replace("[[" + pair.Key + "]]", pair.Value); } return index; } protected void InterfaceCommands(string area, API_supported_interface shared_interface, bool track_commands = false) { string[] cmds = shared_interface.GetCommandsList(); string interface_name = shared_interface.GetType().Name; foreach (string c in cmds) { if (track_commands == true) { if (seen_command_names.ContainsKey(c) == false) { seen_command_names.Add(c, interface_name); } else { LogFormater.Debug("command " + c + " from " + interface_name + " overlaps an ready loaded command from " + seen_command_names[c] + ""); } } string workspace = shared_interface.GetCommandWorkspace(c); StringBuilder sb = new StringBuilder(); sb.Append(html_header); sb.Append("

Build: "); sb.Append(buildVersion); sb.Append("


"); sb.Append("

Interface: [[AREA]]"); if (workspace != "") { sb.Append(" / [[WORKSPACE]]"); } sb.Append("


[[COMMAND]]

"); int loop = 0; int minargs = shared_interface.GetCommandArgs(c); string[] arg_types = shared_interface.GetCommandArgTypes(c); string[] arg_hints = shared_interface.GetCommandArgHints(c); if (area == "Core") { StringBuilder ExampleCall = new StringBuilder(); ExampleCall.Append("Example: [[COMMAND]]"); ExampleCall.Append("|||"); string addon = ""; while (loop < minargs) { ExampleCall.Append(addon); addon = "~#~"; string hint_value = ""; if (arg_hints.Length > loop) { if (arg_hints[loop] != null) { string[] bits = arg_hints[loop].Split("
", StringSplitOptions.RemoveEmptyEntries); if (bits.Length >= 1) { hint_value = bits[0]; } } } if (hint_value != "") { ExampleCall.Append(hint_value); } else { ExampleCall.Append("?"); LogFormater.Debug("[WikiMake] " + area + " Command " + c + " missing some required hint values"); } loop++; } sb.Append(ExampleCall.ToString()); sb.Append("
"); } sb.Append("[[HELP]]"); if (arg_types.Length > 0) { sb.Append("

Args helper

"); loop = 0; sb.Append(""); while (loop < arg_types.Length) { string hint = ""; if (arg_hints.Length > loop) { hint = arg_hints[loop]; } string Required = "X"; if ((loop + 1) > minargs) { Required = ""; } sb.Append(""); loop++; } sb.Append("
NumTypeRequiredHint
" + (loop + 1).ToString() + "" + arg_types[loop] + "" + Required + "" + hint + "
"); } sb.Append(html_footer); sb.Replace("[[COMMAND]]", c); sb.Replace("[[HELP]]", shared_interface.GetCommandHelp(c)); sb.Replace("[[MINARGS]]", minargs.ToString()); sb.Replace("[[WORKSPACE]]", workspace); sb.Replace("[[AREA]]", area); sb.Replace("[[SUBFOLDER]]", ""); sb.Replace("[[RETURNROOT]]", "../"); sb = DebugModeCreateWiki.MenuActive(sb, area); string target_file = "" + area + "" + workspace + "" + c + ".html"; io.writefile(target_file, sb.ToString()); } } protected void InterfaceWorkspaces(string area, API_supported_interface shared_interface) { string[] cmds = shared_interface.GetCommandsList(); foreach (string workspace in shared_interface.GetAllWorkspaces()) { StringBuilder sb = new StringBuilder(); sb.Append(html_header); sb.Append("

Interface: [[AREA]]"); if (workspace != "") { sb.Append(" / [[WORKSPACE]]"); } sb.Append("


"); sb.Append("

Build: "); sb.Append(buildVersion); sb.Append("


"); sb.Append(""); foreach (string c in cmds) { if (shared_interface.GetCommandWorkspace(c) == workspace) { int args = shared_interface.GetCommandArgs(c); sb.Append(""); } } sb.Append("
CommandMin args
"); sb.Append(c); sb.Append(""); sb.Append(args.ToString()); sb.Append("
"); sb.Replace("[[SUBFOLDER]]", ""); sb.Replace("[[RETURNROOT]]", "../"); sb.Replace("[[WORKSPACE]]", workspace); sb.Replace("[[AREA]]", area); sb.Append(html_footer); sb = DebugModeCreateWiki.MenuActive(sb, area); string target_file = "" + area + "" + workspace + ".html"; io.writefile(target_file, sb.ToString()); } } protected void InterfaceIndex(string area, API_supported_interface shared_interface) { StringBuilder sb = new StringBuilder(); sb.Append(html_header); sb.Append("

Interface:"); sb.Append(area); sb.Append("


"); sb.Append("

Build: "); sb.Append(buildVersion); sb.Append("


"); string[] cmds = shared_interface.GetCommandsList(); sb.Append(""); foreach (string workspace in shared_interface.GetAllWorkspaces()) { int commands_count = 0; foreach (string c in cmds) { if (shared_interface.GetCommandWorkspace(c) == workspace) { commands_count++; } } string workspace_link = "" + workspace + ""; sb.Append(""); } sb.Append("
WorkspaceCommands
"); sb.Append(workspace_link); sb.Append(""); sb.Append(commands_count.ToString()); sb.Append("
"); sb.Replace("[[SUBFOLDER]]", ""); sb.Replace("[[RETURNROOT]]", "../"); sb.Replace("[[AREA]]", area); sb.Append(html_footer); sb = DebugModeCreateWiki.MenuActive(sb, area); io.writefile("" + area + ".html", sb.ToString()); } protected void InterfaceWiki(string area, API_supported_interface shared_interface, bool track_commands = false) { LogFormater.Info("[WIKI] Starting area " + area + ""); // create index InterfaceIndex(area, shared_interface); // create workspaces InterfaceWorkspaces(area, shared_interface); // create commands InterfaceCommands(area, shared_interface, track_commands); LogFormater.Info("[WIKI] Done with area"); } public DebugModeCreateWiki(string Version, SimpleIO shareio) { io = shareio; buildVersion = Version; html_header = helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "wiki_header.txt"); html_footer = helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "wiki_footer.txt"); io.ChangeRoot("wiki"); io.ChangeRoot("wiki/files"); // JSONcfg MakeJsonConfig defaultJson = new MakeJsonConfig(); api_reports.Add("JSON", new KeyValuePair(defaultJson.ApiCommandsCount, "Ready")); InterfaceWiki("JSON", defaultJson); // CMD BSB.Commands.CoreCommandsInterface cmd = new BSB.Commands.CoreCommandsInterface(null); api_reports.Add("Core", new KeyValuePair(cmd.ApiCommandsCount, "Good")); InterfaceWiki("Core", cmd, true); // RLVapi BSB.RLV.RLVcontrol RLVapi = new BSB.RLV.RLVcontrol(null); api_reports.Add("RLVapi", new KeyValuePair(RLVapi.ApiCommandsCount, "Limited")); InterfaceWiki("RLVapi", RLVapi, true); // HTTP HTTPWiki(); io.ChangeRoot("wiki"); io.writefile("index.html", CreateRoot()); } protected void HTTPWiki() { LogFormater.Info("[WIKI] Starting area HTTP endpoint"); HTTPendpoint HTTP = new HTTPendpoint(); HTTPmenu("HTTP", HTTP); // create workspaces HTTPWorkspaces("HTTP", HTTP); // create commands HTTPCommands("HTTP", HTTP); HTTP = null; LogFormater.Info("[WIKI] Done with area"); } protected string getURLargs(Dictionary> values) { List urlargs = new List(); foreach (KeyValuePair> entry in values) { if (entry.Value.Key == "URLARG") { urlargs.Add("{"+entry.Key+"}"); } } return String.Join('/', urlargs); } protected void HTTPCommands(string area, HTTPendpoint HTTP) { foreach (string workspace in HTTP.getEndPoints()) { foreach (string c in HTTP.getEndpointCommands(workspace)) { StringBuilder sb = new StringBuilder(); sb.Append(html_header); sb.Append("

Build: "); sb.Append(buildVersion); sb.Append("


"); sb.Append("

Interface: [[AREA]]"); if (workspace != "") { sb.Append(" / [[WORKSPACE]]"); } sb.Append("


[[COMMAND]]

"); sb.Append("[[URLENDPOINT]]/[[WORKSPACE]]/[[COMMAND]]/[[URLADDON]]
"); sb.Append("Method: [[APIMETHOD]]"); sb.Append("
"); sb.Append("[[HELP]]"); Dictionary> values = HTTP.getCommandArgs(workspace, c); int ValueCount = values.Count; if (ValueCount > 0) { sb.Append("

Args helper

"); sb.Append(""); foreach (KeyValuePair> entry in values) { string hint = entry.Value.Value; string type = entry.Value.Key; if (entry.Value.Key.Contains("Optional") == true) { type = type.Replace("Optional", "{Optional} "); } else if (entry.Value.Key == "URLARG") { type = "URL arg"; } sb.Append(""); } sb.Append("
NameTypeHint
" + entry.Key + "" + type + "" + hint + "
"); } string[] returnvalues = HTTP.getReturnsValues(workspace, c); if (returnvalues.Length > 0) { sb.Append("

Possible replys

"); sb.Append("
    "); foreach (string entry in returnvalues) { sb.Append("
  • "+entry+"
  • "); } sb.Append("
"); } sb = DebugModeCreateWiki.MenuActive(sb, area); sb.Append(html_footer); sb.Replace("[[COMMAND]]", c); sb.Replace("[[URLENDPOINT]]", "http://localhost:8080"); sb.Replace("[[APIMETHOD]]", HTTP.getCommandMethod(workspace, c)); sb.Replace("[[URLADDON]]", getURLargs(values)); sb.Replace("[[HELP]]", HTTP.getCommandAbout(workspace, c)); sb.Replace("[[MINARGS]]", ValueCount.ToString()); sb.Replace("[[WORKSPACE]]", workspace); sb.Replace("[[AREA]]", area); sb.Replace("[[SUBFOLDER]]", ""); sb.Replace("[[RETURNROOT]]", "../"); string target_file = "" + area + "" + workspace + "" + c + ".html"; io.writefile(target_file, sb.ToString()); } } } protected void HTTPmenu(string area, HTTPendpoint HTTP) { api_reports.Add(area, new KeyValuePair(HTTP.getFullCount(), "Basic")); // create index StringBuilder sb = new StringBuilder(); sb.Append(html_header); sb.Append("

Interface:"); sb.Append("HTTP"); sb.Append("


"); sb.Append("

Build: "); sb.Append(buildVersion); sb.Append("


"); sb.Append(""); foreach (string workspace in HTTP.getEndPoints()) { string workspace_link = "" + workspace + ""; sb.Append(""); } sb.Append("
WorkspaceCommands
"); sb.Append(workspace_link); sb.Append(""); sb.Append(HTTP.getEndpointCount(workspace).ToString()); sb.Append("
"); sb.Replace("[[SUBFOLDER]]", ""); sb.Replace("[[RETURNROOT]]", "../"); sb.Replace("[[AREA]]", area); sb.Append(html_footer); sb = DebugModeCreateWiki.MenuActive(sb, area); io.writefile("" + area + ".html", sb.ToString()); } protected void HTTPWorkspaces(string area, HTTPendpoint HTTP) { foreach (string workspace in HTTP.getEndPoints()) { StringBuilder sb = new StringBuilder(); sb.Append(html_header); sb.Append("

Interface: [[AREA]]"); if (workspace != "") { sb.Append(" / [[WORKSPACE]]"); } sb.Append("


"); sb.Append("

Build: "); sb.Append(buildVersion); sb.Append("


"); sb.Append(""); foreach (string c in HTTP.getEndpointCommands(workspace)) { int args = HTTP.getCommandArgCount(workspace, c); sb.Append(""); } sb.Append("
CommandMin args
"); sb.Append(c); sb.Append(""); sb.Append(args.ToString()); sb.Append("
"); sb.Replace("[[SUBFOLDER]]", ""); sb.Replace("[[RETURNROOT]]", "../"); sb.Replace("[[WORKSPACE]]", workspace); sb.Replace("[[AREA]]", area); sb.Append(html_footer); sb = DebugModeCreateWiki.MenuActive(sb, area); string target_file = "" + area + "" + workspace + ".html"; io.writefile(target_file, sb.ToString()); } } } public class HTTPendpoint { protected List endpoints = new List(); public HTTPendpoint() { Endpoint core = new Endpoint(); core.name = "core"; core.callable.Add(new gettoken()); core.callable.Add(new logout()); core.callable.Add(new version()); core.callable.Add(new name()); core.callable.Add(new command()); core.callable.Add(new friends()); core.callable.Add(new nearme()); core.callable.Add(new hello()); endpoints.Add(core); Endpoint inventory = new Endpoint(); inventory.name = "inventory"; inventory.callable.Add(new contents()); inventory.callable.Add(new folders()); inventory.callable.Add(new rename()); inventory.callable.Add(new realuuid()); inventory.callable.Add(new send()); inventory.callable.Add(new delete()); endpoints.Add(inventory); Endpoint im = new Endpoint(); im.name = "im"; im.callable.Add(new chatwindows()); im.callable.Add(new listwithunread()); im.callable.Add(new haveunreadims()); im.callable.Add(new getimchat()); im.callable.Add(new sendimchat()); endpoints.Add(im); Endpoint group = new Endpoint(); group.name = "group"; group.callable.Add(new listgroups()); group.callable.Add(new listgroupswithunread()); group.callable.Add(new haveunreadgroupchat()); group.callable.Add(new getgroupchat()); group.callable.Add(new sendgroupchat()); endpoints.Add(group); Endpoint chat = new Endpoint(); chat.name = "chat"; chat.callable.Add(new localchathistory()); chat.callable.Add(new localchatsay()); endpoints.Add(chat); } public string getCommandMethod(string endpoint, string command) { foreach (Endpoint End in endpoints) { if (End.name == endpoint) { foreach (APIcall api in End.callable) { if (api.name == command) { return api.type; } } } } return "?"; } public string getCommandAbout(string endpoint, string command) { foreach (Endpoint End in endpoints) { if (End.name == endpoint) { foreach (APIcall api in End.callable) { if (api.name == command) { return api.about; } } } } return "?"; } public string[] getReturnsValues(string endpoint, string command) { foreach (Endpoint End in endpoints) { if (End.name == endpoint) { foreach (APIcall api in End.callable) { if (api.name == command) { return api.returns.ToArray(); } } } } return new string[] { }; } public int getCommandArgCount(string endpoint, string command) { foreach (Endpoint End in endpoints) { if (End.name == endpoint) { foreach (APIcall api in End.callable) { if (api.name == command) { return api.values.Count; } } } } return 0; } public string[] getEndpointCommands(string endpointname) { List commands = new List(); foreach (Endpoint End in endpoints) { if (End.name == endpointname) { foreach (APIcall api in End.callable) { commands.Add(api.name); } } } return commands.ToArray(); } public string[] getEndPoints() { List names = new List(); foreach (Endpoint End in endpoints) { names.Add(End.name); } return names.ToArray(); } public int getEndpointCount(string endpointname) { foreach (Endpoint End in endpoints) { if (End.name == endpointname) { return End.callable.Count; } } return 0; } public int getFullCount() { int count = 0; foreach (Endpoint End in endpoints) { count += End.callable.Count; } return count; } public Dictionary> getCommandArgs(string endpoint, string command) { Dictionary> empty = new Dictionary>(); foreach (Endpoint End in endpoints) { if (End.name == endpoint) { foreach (APIcall api in End.callable) { if (api.name == command) { return api.values; } } } } return empty; } } public class Endpoint { public string name = "Notset"; public List callable = new List(); } abstract public class APIcall { public string name { get { return GetType().Name.ToLowerInvariant(); } } public string type = "get"; public string about = "A API call that is missing its about value"; public Dictionary> values = new Dictionary>(); public List returns = new List(); public bool RequiresToken = true; public APIcall() { Setup(); } public virtual void Setup() { if (RequiresToken == true) { returns.Add("Token not accepted"); values.Add( "token", new KeyValuePair( "URLARG", "the api access token") ); } } } abstract public class postAPIcall : APIcall { public override void Setup() { type = "post"; base.Setup(); } } public class gettoken : postAPIcall { public override void Setup() { RequiresToken = false; about = "Requests a new token (Vaild for 10 mins)
to use with all other requests"; values.Add("Authcode", new KeyValuePair("string", "the first 10 chars of SHA1(unixtime+WebUIkey)
unixtime can be +- 30 of the bots time.")); returns = new List(); returns.Add("Authcode not accepted"); returns.Add("New API Token"); base.Setup(); } } public class logout : APIcall { public override void Setup() { about = "A API call that is missing its about value"; returns.Add("ok"); returns.Add("Failed to remove token"); base.Setup(); } } public class version : APIcall { public override void Setup() { about = "Gets the bots build version"; returns.Add("Bot build version"); base.Setup(); } } public class friends : APIcall { public override void Setup() { about = "Gets the friendslist
Formated as follows
friendreplyobject
  • name: String
  • id: String
  • online: bool
"; returns.Add("array UUID = friendreplyobject"); base.Setup(); } } public class nearme : APIcall { public override void Setup() { about = "returns a list of all known avatars near (same sim)>"; returns.Add("array UUID = Name"); base.Setup(); } } public class hello : APIcall { public override void Setup() { RequiresToken = false; about = "used to test you can talk to the api but mostly pointless."; returns.Add("world"); base.Setup(); } } public class name : APIcall { public override void Setup() { about = "Gets the name of the bot"; returns.Add("Fistname Lastname"); base.Setup(); } } public class command : postAPIcall { public override void Setup() { about = "Makes a request to the core commands lib"; values.Add( "body", new KeyValuePair( "JsonObject", "A JSON object formated as follows
Command: string
Args: string[]
AuthCode: string
========
See LSL example on how to create a core command auth code") ); returns.Add("accepted"); base.Setup(); } } public class contents : APIcall { public override void Setup() { about = "Requests the contents of a folder as an array of InventoryMapItem
Formated as follows
InventoryMapItem
  • id: UUID
  • name: String
  • typename: String
"; values.Add( "folderUUID", new KeyValuePair( "URLARG", "the folder to fetch (Found via: inventory/folders)") ); returns.Add("array of InventoryMapItem"); base.Setup(); } } public class folders : APIcall { public override void Setup() { about = "Requests the inventory folder layout as a json object InventoryMapFolder
Formated as follows
InventoryMapItem
  • id: UUID
  • name: String
  • subfolders: InventoryMapFolder[]
"; returns.Add("array of InventoryMapFolder"); base.Setup(); } } public class rename : postAPIcall { public override void Setup() { about = "renames a folder or inventory item"; returns.Add("true|false"); values.Add("item", new KeyValuePair("URLARG", "UUID of the item/folder we are working on")); values.Add("newname", new KeyValuePair("string", "What we are setting")); base.Setup(); } } public class realuuid : APIcall { public override void Setup() { about = "converts a inventory uuid to a realworld uuid
Needed for texture preview"; returns.Add("Failed"); returns.Add("UUID"); values.Add("item", new KeyValuePair("URLARG", "UUID of the item/folder we are working on")); base.Setup(); } } public class send : APIcall { public override void Setup() { about = "sends a item to an avatar"; returns.Add("Failed"); returns.Add("UUID"); values.Add("item", new KeyValuePair("URLARG", "UUID of the item we are working on")); values.Add("avatar", new KeyValuePair("URLARG", "a UUID or Firstname Lastname")); base.Setup(); } } public class delete : APIcall { public override void Setup() { about = "Removes a item/folder from inventory (Make sure you set the isfolder flag correctly!)"; returns.Add("Failed"); returns.Add("UUID"); values.Add("item", new KeyValuePair("URLARG", "UUID of the item/folder we are working on")); values.Add("isfolder", new KeyValuePair("URLARG", "true or false if this is a folder")); base.Setup(); } } public class chatwindows : APIcall { public override void Setup() { about = "gets a full list of all chat windows"; returns.Add("array UUID = Name"); base.Setup(); } } public class listwithunread : APIcall { public override void Setup() { about = "gets a list of chat windows with unread messages"; returns.Add("array of UUID"); base.Setup(); } } public class haveunreadims : APIcall { public override void Setup() { about = "gets if there are any unread im messages at all"; returns.Add("true|false"); base.Setup(); } } public class getimchat : APIcall { public override void Setup() { about = "gets the chat from the selected window"; values.Add("window", new KeyValuePair("URLARG", "the UUID of the chat window")); returns.Add("Chat contents"); returns.Add("Window UUID invaild"); base.Setup(); } } public class sendimchat : postAPIcall { public override void Setup() { about = "sends a im to the selected avatar"; values.Add("avatar", new KeyValuePair("URLARG", "a UUID or Firstname Lastname")); values.Add("message", new KeyValuePair("string", "the message to send")); returns.Add("ok"); base.Setup(); } } public class listgroups : APIcall { public override void Setup() { about = "fetchs a list of all groups known to the bot"; returns.Add("array UUID=name"); base.Setup(); } } public class listgroupswithunread : APIcall { public override void Setup() { about = "fetchs a list of all groups with unread messages"; returns.Add("array UUID"); base.Setup(); } } public class haveunreadgroupchat : APIcall { public override void Setup() { about = "checks if there are any groups with unread messages"; returns.Add("true|false"); base.Setup(); } } public class getgroupchat : APIcall { public override void Setup() { about = "fetchs the groupchat history"; values.Add("group ", new KeyValuePair("URLARG", "UUID of the group")); returns.Add("Group UUID invaild"); returns.Add("Group Chat"); base.Setup(); } } public class sendgroupchat : postAPIcall { public override void Setup() { about = "sends a message to the groupchat"; values.Add("group ", new KeyValuePair("URLARG", "UUID of the group")); values.Add("message ", new KeyValuePair("string", "the message to send")); returns.Add("Group UUID invaild"); returns.Add("Processing"); base.Setup(); } } public class localchathistory : APIcall { public override void Setup() { about = "fetchs the last 20 localchat messages"; returns.Add("array string"); base.Setup(); } } public class localchatsay : postAPIcall { public override void Setup() { about = "sends a message to localchat"; values.Add("message ", new KeyValuePair("string", "the message to send")); returns.Add("see->localchathistory"); base.Setup(); } } }