From 35a54a4e940f93db9cdc74f71f5f6ed193476663 Mon Sep 17 00:00:00 2001 From: Madpeter Date: Mon, 11 May 2020 22:15:34 +0100 Subject: [PATCH] Start of the web UI project --- BSBshared/Json/JsonConfigApi.cs | 2 +- BSBshared/Staic/Helpers.cs | 51 ++++++++++++ CLI/BetterSecondBot.csproj | 20 ++++- CLI/HttpServer/SecondBotHttpServer.cs | 21 ++--- CLI/HttpServer/control/Actions/logout.cs | 2 +- CLI/HttpServer/control/Interface/cmd_lib.cs | 2 +- CLI/HttpServer/http_commands.cs | 30 +------ CLI/HttpServer/view/Basic/status.cs | 30 ------- CLI/HttpWebUi/theme/css/site.css | 4 + CLI/HttpWebUi/theme/images/favicon-32x32.png | Bin 0 -> 4572 bytes CLI/HttpWebUi/theme/images/logo.png | Bin 0 -> 28566 bytes CLI/HttpWebUi/theme/js/site.js | 75 ++++++++++++++++++ CLI/HttpWebUi/theme/layout/cdn.css.layout | 2 + CLI/HttpWebUi/theme/layout/cdn.js.layout | 3 + CLI/HttpWebUi/theme/layout/full.layout | 33 ++++++++ CLI/HttpWebUi/theme/layout/login.block | 14 ++++ CLI/HttpWebUi/theme/layout/sidemenu.layout | 59 ++++++++++++++ CLI/HttpWebUi/webui.cs | 79 +++++++++++++++++++ CLI/WikiMake/wiki_header.txt | 1 - CLI/WikiMake/wikimake.cs | 36 ++------- 20 files changed, 359 insertions(+), 105 deletions(-) delete mode 100644 CLI/HttpServer/view/Basic/status.cs create mode 100644 CLI/HttpWebUi/theme/css/site.css create mode 100644 CLI/HttpWebUi/theme/images/favicon-32x32.png create mode 100644 CLI/HttpWebUi/theme/images/logo.png create mode 100644 CLI/HttpWebUi/theme/js/site.js create mode 100644 CLI/HttpWebUi/theme/layout/cdn.css.layout create mode 100644 CLI/HttpWebUi/theme/layout/cdn.js.layout create mode 100644 CLI/HttpWebUi/theme/layout/full.layout create mode 100644 CLI/HttpWebUi/theme/layout/login.block create mode 100644 CLI/HttpWebUi/theme/layout/sidemenu.layout create mode 100644 CLI/HttpWebUi/webui.cs diff --git a/BSBshared/Json/JsonConfigApi.cs b/BSBshared/Json/JsonConfigApi.cs index fcb307f..f92dd20 100644 --- a/BSBshared/Json/JsonConfigApi.cs +++ b/BSBshared/Json/JsonConfigApi.cs @@ -220,7 +220,7 @@ namespace BetterSecondBotShared.Json { ConsoleLog.Warn("Http disabled: Httpkey length must be 12 or more"); } - else if (jsonConfig.Httpport < 81) + else if (jsonConfig.Httpport < 80) { ConsoleLog.Warn("Http disabled: Httpport range below protected range - Given: (" + jsonConfig.Httpport + ")"); } diff --git a/BSBshared/Staic/Helpers.cs b/BSBshared/Staic/Helpers.cs index 18e66cb..2b1321c 100644 --- a/BSBshared/Staic/Helpers.cs +++ b/BSBshared/Staic/Helpers.cs @@ -1,8 +1,11 @@ using BetterSecondBotShared.Json; using BetterSecondBotShared.logs; +using Microsoft.Extensions.ObjectPool; using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Reflection; using System.Security.Cryptography; using System.Text; @@ -22,6 +25,54 @@ namespace BetterSecondBotShared.Static } public static class helpers { + // + + public static byte[] ReadResourceFileBinary(Assembly targetenv, string filename) + { + try + { + byte[] dataset; + string[] files = targetenv.GetManifestResourceNames(); + string resourceName = files.Single(str => str.EndsWith(filename)); + using (Stream stream = targetenv.GetManifestResourceStream(resourceName)) + using (BinaryReader br = new BinaryReader(stream)) + { + const int bufferSize = 4096; + using (var ms = new MemoryStream()) + { + byte[] buffer = new byte[bufferSize]; + int count; + while ((count = br.Read(buffer, 0, buffer.Length)) != 0) + ms.Write(buffer, 0, count); + dataset = ms.ToArray(); + } + } + return dataset; + } + catch (Exception e) + { + return Encoding.UTF8.GetBytes(e.Message); + } + } + public static string ReadResourceFile(Assembly targetenv,string filename) + { + try + { + string[] files = targetenv.GetManifestResourceNames(); + string resourceName = files.Single(str => str.EndsWith(filename)); + string result = ""; + using (Stream stream = targetenv.GetManifestResourceStream(resourceName)) + using (StreamReader reader = new StreamReader(stream)) + { + result = reader.ReadToEnd(); + } + return result; + } + catch (Exception e) + { + return e.Message; + } + } public static bool inrange(float current,float min,float max) { if(current <= max) diff --git a/CLI/BetterSecondBot.csproj b/CLI/BetterSecondBot.csproj index 36bb74d..a4a98b0 100644 --- a/CLI/BetterSecondBot.csproj +++ b/CLI/BetterSecondBot.csproj @@ -3,7 +3,7 @@ AnyCPU;x64 - + git describe --long --always @@ -26,6 +26,15 @@ linux-x64 + + + + + + + + + @@ -37,6 +46,15 @@ + + + + + + + + + diff --git a/CLI/HttpServer/SecondBotHttpServer.cs b/CLI/HttpServer/SecondBotHttpServer.cs index dd8bbf1..9870093 100644 --- a/CLI/HttpServer/SecondBotHttpServer.cs +++ b/CLI/HttpServer/SecondBotHttpServer.cs @@ -1,4 +1,5 @@ -using BetterSecondBotShared.IO; +using BetterSecondBot.HttpWebUi; +using BetterSecondBotShared.IO; using BetterSecondBotShared.Json; using BetterSecondBotShared.logs; using BetterSecondBotShared.Static; @@ -22,8 +23,7 @@ namespace BetterSecondBot.HttpServer public SecondBot GetBot { get { return Bot; } } protected JsonConfig Config; public JsonConfig GetConfig { get { return Config; } } - protected HTTPCommandsInterfaceGet get_controler; - protected HTTPCommandsInterfacePost post_controler; + protected HTTPCommandsInterface post_controler; protected string url = ""; public bool ShutdownHTTP { get; set; } public bool HTTPCnCmode { get; set; } @@ -93,6 +93,7 @@ namespace BetterSecondBot.HttpServer protected async Task HandleIncomingConnections() { + webui myUI = new webui(Config,Bot); while (Bot.KillMe == false) { HttpListenerContext ctx = await listener.GetContextAsync(); @@ -107,16 +108,11 @@ namespace BetterSecondBot.HttpServer byte[] data; resp.StatusCode = 200; resp.ContentType = "text/html"; - resp.ContentEncoding = Encoding.UTF8; if (req.HttpMethod == "GET") { - string command = "status"; - if (http_args.Count > 0) - { - command = http_args.Last(); - } - string content = String.Join("{@}", get_controler.Call(command, "")); - data = Encoding.UTF8.GetBytes(content); + KeyValuePair replydata = myUI.process(http_args, req.Cookies); + resp.ContentType = replydata.Key; + data = replydata.Value; resp.ContentLength64 = data.LongLength; await resp.OutputStream.WriteAsync(data, 0, data.Length); resp.Close(); @@ -190,8 +186,7 @@ namespace BetterSecondBot.HttpServer } protected void OpenHttpService() { - get_controler = new HTTPCommandsInterfaceGet(Bot,this); - post_controler = new HTTPCommandsInterfacePost(Bot,this); + post_controler = new HTTPCommandsInterface(Bot,this); Thread t = new Thread(delegate (object _) { bool ok = true; diff --git a/CLI/HttpServer/control/Actions/logout.cs b/CLI/HttpServer/control/Actions/logout.cs index 646d120..76f314d 100644 --- a/CLI/HttpServer/control/Actions/logout.cs +++ b/CLI/HttpServer/control/Actions/logout.cs @@ -4,7 +4,7 @@ using System.Text; namespace BetterSecondBot.HttpServer.Control.Actions { - public class Logout : HTTP_commands_post + public class Logout : HTTP_commands { public override string Helpfile { get { return "Makes the bot logout
Returns OK,I dont want to go if accepted"; } } diff --git a/CLI/HttpServer/control/Interface/cmd_lib.cs b/CLI/HttpServer/control/Interface/cmd_lib.cs index 9afe597..5dccba1 100644 --- a/CLI/HttpServer/control/Interface/cmd_lib.cs +++ b/CLI/HttpServer/control/Interface/cmd_lib.cs @@ -5,7 +5,7 @@ using System.Text; namespace BetterSecondBot.HttpServer.Control.Interface { - public class CoreCMD : HTTP_commands_post + public class CoreCMD : HTTP_commands { public override string[] ArgTypes { get { return new [] { "Text","Text" }; } } public override string[] ArgHints { get { return new [] { "Command","Args (~#~ split)" }; } } diff --git a/CLI/HttpServer/http_commands.cs b/CLI/HttpServer/http_commands.cs index 9ead6c5..c5ca419 100644 --- a/CLI/HttpServer/http_commands.cs +++ b/CLI/HttpServer/http_commands.cs @@ -11,15 +11,17 @@ using BetterSecondBotShared.logs; namespace BetterSecondBot.HttpServer { - public abstract class HTTPCommandsInterface : API_supported_interface + public class HTTPCommandsInterface : API_supported_interface { protected SecondBot bot; protected SecondBotHttpServer httpserver; - protected HTTPCommandsInterface(SecondBot linktobot, SecondBotHttpServer sethttpserver) + public HTTPCommandsInterface(SecondBot linktobot, SecondBotHttpServer sethttpserver) { bot = linktobot; httpserver = sethttpserver; + API_type = typeof(HTTP_commands); + LoadCommandsList(); } public string[] Call(string command, string arg) @@ -38,30 +40,6 @@ namespace BetterSecondBot.HttpServer } } } - public class HTTPCommandsInterfaceGet : HTTPCommandsInterface - { - public HTTPCommandsInterfaceGet(SecondBot linktobot, SecondBotHttpServer sethttpserver) : base(linktobot, sethttpserver) - { - API_type = typeof(HTTP_commands_get); - LoadCommandsList(); - } - } - public class HTTPCommandsInterfacePost : HTTPCommandsInterface - { - public HTTPCommandsInterfacePost(SecondBot linktobot, SecondBotHttpServer sethttpserver) : base(linktobot, sethttpserver) - { - API_type = typeof(HTTP_commands_post); - LoadCommandsList(); - } - } - - - public abstract class HTTP_commands_get : HTTP_commands - { - } - public abstract class HTTP_commands_post : HTTP_commands - { - } public abstract class HTTP_commands : API_interface { diff --git a/CLI/HttpServer/view/Basic/status.cs b/CLI/HttpServer/view/Basic/status.cs deleted file mode 100644 index 064375f..0000000 --- a/CLI/HttpServer/view/Basic/status.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace BetterSecondBot.HttpServer.View.Basic -{ - public class Status : HTTP_commands_get - { - public override string Helpfile { get { return "returns the status of the bot"; } } - - public override string[] CallFunction(string[] args) - { - if (bot != null) - { - if (ArgsCheck(args) == true) - { - return new string[] { bot.GetStatus() }; - } - else - { - return Failed("Incorrect number of args"); - } - } - else - { - return Failed("No Bot"); - } - } - } -} diff --git a/CLI/HttpWebUi/theme/css/site.css b/CLI/HttpWebUi/theme/css/site.css new file mode 100644 index 0000000..582030c --- /dev/null +++ b/CLI/HttpWebUi/theme/css/site.css @@ -0,0 +1,4 @@ +.logo +{ + width: 100%; +} diff --git a/CLI/HttpWebUi/theme/images/favicon-32x32.png b/CLI/HttpWebUi/theme/images/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..dc83cd083845b1897b461451512579d8e6c47bb7 GIT binary patch literal 4572 zcmc&&3s@6Z7M_6eP!X*a)K(m$R$Lr1lT2PC5!6sY2~r*^KAFr+U=%Vj6CfZ$N-YXn zZLL~G-Bv`3V5wkj6$@xZ)JiRgMa5Q>LW|gnukx~$orH(DmFm~s{WjkhGP(CZ=lu8F z|D1b6YJmT2he2Zo0RZ6O>!S?hK0))_&W8KT#>YS8KJ0Zqp)3HnPcXlE#{Hf#05CY8 z4qj+jsPe-ICdwTr88zi@jM8yv0PyfM>TqHuWdPMwIIUIin~#_9L7G(X7l>7`N;iv& zpnc-?R8YKsFcH6!kdu7R>7a)Z;~Yd$1{^d-MQT~hsNh@tV%)QNSilD@5W`9Ze}*|A zxKI@U&SLZwD0Y`X1cC}dsoWirz;Yov6%@jVQ~*l_hzNoa43=ObIoSQ;bJ6sq1`AZa z-W`kkrr<{y3_468h>eYPj}^Hy`fvdvm&*mPP#_dS90FqFv}! zYhXDn(u?J?q*C?5pXoL#su#@~ykj^<-D`U$nhlQAQG!53*Q*nO>+4o29341EUXSn8+UO z1oUtNXU#HeMFzSqptU3u%T6(`z1xOT;s#2=7s5gqf<=%}9*l@FScJi12$o_n+yzx} z>LhUk-WQB=stZP>7$V0I>8;)`AIjXq1 z#1wp_dvKvyt&!1PgCf}S5^&tiJ7Td4eIDS+e2A9jk}TwdX3=0420>i^;wVVOVv)Fe zJb*S*kqebHmp8VH3M}LjYO%4*h4z^fBSLeBuv9AML$jRr;<|fI5VflNDUt>)#fjlW z*E$HZN-2`xJxo7imtQQOU2bC|C@y1vA>A$*%V-R-xSpC3&ZYT9szcBpe-@AVYxXjU zS|~!~BqY>`C6HQ;!VnJ2aEL+?IWC6PVxdspv-&@?mtZJ@i6lL>^f%deCzpu8wc!+Z zBnkL`e?4k3isGb11QDo&f(Q~NAT=uCiUuJlp_r88D8b3+&%5!=-tfO)55Z_-D19G= z>2N*Hovf6eRq!=>CJMxLx=5O^)S4hhOLiYvz2ylS81P9m>NjsBrKkHSp>LF43gCY+ z-g9;LV!iSIu}=c?rJ<`O2>!iWbbVKLCG&Oj_E-*M>{)%`MU}{%&KTG0pVR$G9F5jzTDml3cM85=bVJNyS0}SCc}n`**Qn{?qPnmQk<5uwcq)@WbOcNp^RcnRxh< ze)9xp!T59PRq%uQ9w3%+vlH`pAB8^Ca%Ml4GoNd@xF5^K&$V3IkL6N}r9}^2OBOt# z{8UmbkUsZLE<2VX?lNnB?7c;EUwZH1l$PssdhV9(eYNye02o;5tDF(M@a=a#SnM}) z_NX(RtL5vg->5h7n)a`?9+RwCky#I3T6WOcO1;td+SWz(!>cmO7VY~utRt*yZl>>n zy{V2_g14tHJZ-BEO3Qy){@WJyk@4#TE;;3AWZ5LU>RNy);E5!JQYq zLK6bNp8f`#SX1W)qyRpW6K!orXYaNHDkClp2HzAN96T&xK;(~rM^@gk6-^`NtpO5- z0;;OuFV5}Tw{MIoZuhF<`#?-1&j=VZh<#%&ZuhG~Kg+&sWh$~&no?3y(mOgjZUa7t zG800=eoc9I;`xak_4i6*AFuyC@yG9P%>XnM)xaJ*c5H+F_?N~jt5MZ=(MzMWS{E66 zv}rc*NjuXVTBJX}sbSnIgQJ4oIDX)a&j{iKYrZF zg0Y^_uRf}e@bx{nD>O9pxVPX7rgl?taj~eOp`mtXq0^bo!Ztr@$!jo;PtSu5cR#aA2Ua6{Lr2+xt?fPs|zyu#r?P_`DEC#kdTmJ!G?Eh{O3JbGS#u;cuH|? zQGUzij?E>vXvI}j-x}li%HV@P97-RiUU{jy+GY7+%{O~>vV@JlZQHhONA}pQJN2`6 zX+%-#Ejh1qh$uU(2@b4Ix_kPk@`{cxN*jF&$_?vRr0yvArO@BU&+nntDCdobC+vKC z%eQNP8Br}wdh@o+`yX#tt&1Kt9LUPa$+|{{gg5{rbU#@SF-@AtH`$tI&o4@!W?C^> zBJr9#ckZ|M8_t)AhrG3C<4gO4)0BK?p2r#+V5j|!J0CjNP~J#evuWZv(s;KT1RPB6 zJfG9S`eC-<^}=`v0k?Yz_i2X%>h_P$B;VD;TsQdaHJ)G265I1DQYT%=9u1VV)VbW? zq32zX-)9C?i2x-}8IpUlF&ij#33F7qO=%FRtuHv7vksWPWr)cE1|FO6H3`)94M60$ zyTI?AJU74D;d4(68D3gFcjKVpdF4mjh_5NBONv}^DnV9j)p}4(w&HsP#_4Zfh%?wNa7q1wxmH+?% literal 0 HcmV?d00001 diff --git a/CLI/HttpWebUi/theme/images/logo.png b/CLI/HttpWebUi/theme/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..540dbeac7ce977451c31f576609179533669f0d4 GIT binary patch literal 28566 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

m~c-ze4G0IB@3eM}I>pli20-WZGpul8L zt>tS*2v`r%{_BrujFRWIutmr3eBt{hY8c8VEAIOs^k=E_|R?+J&Sq51igZ=kh1-qE{LaJAc+2SS&`qIkvt^2%FalpoDi_ z|C!f|i7ie0tb&XCWGs3+^tnMNz~dCl2?{WC6ehQH)z5|a79k|L;D8Pv@}#}%O>&0G z3jK8*9i2` + diff --git a/CLI/HttpWebUi/theme/layout/cdn.js.layout b/CLI/HttpWebUi/theme/layout/cdn.js.layout new file mode 100644 index 0000000..689180f --- /dev/null +++ b/CLI/HttpWebUi/theme/layout/cdn.js.layout @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/CLI/HttpWebUi/theme/layout/full.layout b/CLI/HttpWebUi/theme/layout/full.layout new file mode 100644 index 0000000..b002a70 --- /dev/null +++ b/CLI/HttpWebUi/theme/layout/full.layout @@ -0,0 +1,33 @@ + + + [[html_title]] - [[html_title_after]] + [[html_cs_top]] + + + + +

+
+
+
+
+ +
+
+
+
+ [[page_content]] +
+
+
+
+
+ [[html_js_bottom]] + + + + diff --git a/CLI/HttpWebUi/theme/layout/login.block b/CLI/HttpWebUi/theme/layout/login.block new file mode 100644 index 0000000..c336d96 --- /dev/null +++ b/CLI/HttpWebUi/theme/layout/login.block @@ -0,0 +1,14 @@ +
+
+
Bot webUI auth required
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CLI/HttpWebUi/theme/layout/sidemenu.layout b/CLI/HttpWebUi/theme/layout/sidemenu.layout new file mode 100644 index 0000000..36e5555 --- /dev/null +++ b/CLI/HttpWebUi/theme/layout/sidemenu.layout @@ -0,0 +1,59 @@ + + + [[html_title]] - [[html_title_after]] + [[html_cs_top]] + + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+

+
+
+
+
+
+ +
+
+
+ + +
+
+
+
+
[[page_title]]
+
[[page_actions]]
+
+
+
+ [[page_content]] +
+
+
+
+
+ [[html_js_bottom]] + + + + diff --git a/CLI/HttpWebUi/webui.cs b/CLI/HttpWebUi/webui.cs new file mode 100644 index 0000000..d5838f2 --- /dev/null +++ b/CLI/HttpWebUi/webui.cs @@ -0,0 +1,79 @@ +using BetterSecondBotShared.Json; +using BetterSecondBotShared.Static; +using BSB.bottypes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Reflection; +using System.Text; + +namespace BetterSecondBot.HttpWebUi +{ + public class webui + { + JsonConfig siteconfig; + SecondBot bot; + public webui(JsonConfig setconfig,SecondBot setbot) + { + bot = setbot; + siteconfig = setconfig; + } + public KeyValuePair process(List args,CookieCollection cookies) + { + Cookie logincookie = null; + foreach(Cookie C in cookies) + { + if(C.Name == "logincookie") + { + logincookie = C; + break; + } + } + if (logincookie == null) + { + if (args != null) + { + if (args.Count >= 1) + { + if (args[0] == "theme") + { + if (args.Count >= 2) + { + if (args[1] == "images") + { + return new KeyValuePair("image/png", helpers.ReadResourceFileBinary(Assembly.GetExecutingAssembly(), args[2])); + } + else if (args[1] == "css") + { + return new KeyValuePair("text/css", Encoding.UTF8.GetBytes(helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), args[2]))); + } + else if (args[1] == "js") + { + return new KeyValuePair("text/javascript", Encoding.UTF8.GetBytes(helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), args[2]))); + } + } + } + return new KeyValuePair("text/html", Encoding.UTF8.GetBytes("")); + } + } + string layout = helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "full.layout"); + layout = layout.Replace("[[page_content]]", helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "login.block")); + layout = layout.Replace("[[url_base]]", siteconfig.HttpPublicUrlBase); + layout = layout.Replace("[[html_title_after]]", "Secondbot web UI"); + layout = layout.Replace("[[html_title]]", siteconfig.userName); + layout = layout.Replace("[[html_cs_top]]", helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "cdn.css.layout")); + layout = layout.Replace("[[html_js_bottom]]", helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "cdn.js.layout")); + + layout = layout.Replace("[[html_js_onready]]", ""); + return new KeyValuePair("text/html", Encoding.UTF8.GetBytes(layout)); + + } + else + { + return new KeyValuePair("text/html", Encoding.UTF8.GetBytes("")); + } + } + } + +} diff --git a/CLI/WikiMake/wiki_header.txt b/CLI/WikiMake/wiki_header.txt index de4e535..28a6b76 100644 --- a/CLI/WikiMake/wiki_header.txt +++ b/CLI/WikiMake/wiki_header.txt @@ -16,7 +16,6 @@ Main commands [Core] JSON [Bot Config file] Restrained Love API [RLV] - Get [HTTP] Post [HTTP]