Compare commits

...

35 Commits

Author SHA1 Message Date
JonatanRek
83f2e08bb5 Fix Maxro 2024-10-28 17:19:50 +01:00
JonatanRek
4c07938a0d Fixes + PWA Progress 2024-10-02 12:35:15 +02:00
JonatanRek
df80ce37ed Fixes 2024-09-17 21:39:22 +02:00
JonatanRek
50c6c9a1de Merge branch 'main' of https://git.steelants.cz/JonatanRek/FakeDeck 2024-09-17 21:39:18 +02:00
JonatanRek
0b3822b8da Fixes 2024-09-17 21:36:17 +02:00
a63133a7a5 Merge branch 'main' of https://git.steelants.cz/JonatanRek/FakeDeck 2024-09-17 06:23:19 -07:00
600a08dd51 Process Macro Fixes 2024-09-17 06:23:17 -07:00
Jonatan Rek
9d33f9a223 Readme 2024-09-17 08:21:01 +02:00
Jonatan Rek
ed334a7cf9 Merge branch 'main' of https://git.steelants.cz/JonatanRek/FakeDeck 2024-09-17 08:19:31 +02:00
7fb6b4c89c Process Starting 2024-09-17 06:17:43 -07:00
Jonatan Rek
1666be73b3 Readme 2024-09-17 08:19:21 +02:00
6ab18fdf70 Update FakeDeckUI/FakeDeck/Class/AutoUpdateHelper.cs 2024-09-16 06:52:25 +00:00
JonatanRek
987ccad5b9 Fixes 2024-09-15 14:54:59 +02:00
JonatanRek
027ec1f0d9 Tweaks
Tweaks
2024-09-15 14:42:05 +02:00
7699f5c6b9 Merge branch 'main' of https://git.steelants.cz/JonatanRek/FakeDeck 2024-09-12 19:52:57 -07:00
ac92fcb041 Merge branch 'main' of https://git.steelants.cz/JonatanRek/FakeDeck 2024-09-12 17:58:34 -07:00
849307d2cc Big Proggress 2024-09-12 17:58:22 -07:00
b0bc2fead2 Progression 2024-09-12 13:20:36 -07:00
14877f4711 Tweaks 2024-09-12 13:00:34 -07:00
87a4f569c0 Fixes And Update 2024-09-12 12:54:56 -07:00
Jonatan Rek
59673ec211 REadme Style Fixes 2024-09-12 20:09:44 +02:00
Jonatan Rek
ee39a91229 Readme FIxes 2024-09-12 20:06:56 +02:00
ef59ca9945 Working Configuration 2024-09-12 11:05:00 -07:00
0918ac5a80 Progression And Cleanup 2024-09-12 08:48:11 -07:00
Jonatan Rek
2251de8ce9 Tweaks 2024-09-12 16:09:01 +02:00
Jonatan Rek
f3b56cade2 Fic 2024-09-12 15:46:59 +02:00
Jonatan Rek
b0427e611b FIxes 2024-09-12 15:46:16 +02:00
Jonatan Rek
f31a05dcf4 Readme Tweaks 2024-09-12 15:39:20 +02:00
Jonatan Rek
603a171f1b Merge branch 'main' of https://git.steelants.cz/JonatanRek/FakeDeck 2024-09-12 15:21:01 +02:00
Jonatan Rek
c83c60d2b3 Readme Edits 2024-09-12 15:21:00 +02:00
012cc02352 Streamlining 2024-09-11 12:46:34 -07:00
41aa2b7c7b Tweaks 2024-09-11 07:59:00 -07:00
51d9389f6d Merge branch 'main' of https://git.steelants.cz/JonatanRek/FakeDeck 2024-09-11 07:31:54 -07:00
7bd3664f92 Coment 2024-09-11 07:31:44 -07:00
50d0951b4a Tweaks 2024-09-11 07:31:30 -07:00
31 changed files with 1338 additions and 336 deletions

View File

@@ -0,0 +1,9 @@
<Application x:Class="FakeDeck.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:FakeDeck"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,32 @@
using FakeDeck.Class;
using Microsoft.VisualBasic.Logging;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Windows;
using System.Windows.Forms;
using Application = System.Windows.Application;
namespace FakeDeck
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public YamlHelper yaml;
protected override void OnStartup(StartupEventArgs e)
{
yaml = new YamlHelper();
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
FakeDeckMain fakeDeck = new FakeDeckMain(yaml);
}).Start();
base.OnStartup(e);
}
}
}

View File

@@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrayNotify;
namespace FakeDeck.ButtonType
{
internal class Button
{
public static string getButtonHTML(string icon, string image, string name, string action = null, string jsAction = null, Dictionary<string, string> parameters = null, string color = null)
{
string body = "";
string styles = "style=\"background-size: cover; " + (!string.IsNullOrEmpty(image) ? "background-image: url('" + image + "');" : "") + " width: 150px; height: 150px; " + (!string.IsNullOrEmpty(image) ? "background-image: url('" + image + "');" : "") + (!string.IsNullOrEmpty(color) ? " background-color: " + color + "; " : "") + "\"";
body += "<div>";
if (action != null)
{
body += "<form style=\"margin-bottom: 0px;\" method=\"post\" action=\"" + action + "\">";
if (parameters is not null)
{
foreach (var parameter in parameters)
{
body += "<input type=\"hidden\" name=\"" + parameter.Key + "\" value=\"" + parameter.Value + "\">";
}
}
body += "<button class=\"button\" type=\"submit\" value=\"submit\" " + styles + ">";
body += (!string.IsNullOrEmpty(icon) ? "<i class=\"fa-solid " + icon + "\"></i>" : name);
body += "</button>";
body += "</form>";
}
else if (jsAction != null)
{
body += "<button class=\"button\" onclick=\"" + jsAction + "\" " + styles + " >";
body += (!string.IsNullOrEmpty(icon) ? "<i class=\"fa-solid " + icon + "\"></i>" : name);
body += "</button>";
}
else
{
body += "<div class=\"button\" " + styles + "></div>";
}
body += "</div>";
return body;
}
public static string getButton(string Key)
{
return getButtonHTML(null, "https://docs.itego.cz/uploads/images/system/2022-04/OdRTPJ4iTTInmhdP-jagq7dfjpi2lilfg-imageedit-2-6604933313.gif", "Test", "test/test");
}
public static bool invokeAction(string Key)
{
return false;
}
}
}

View File

@@ -0,0 +1,38 @@
using FakeDeck.ButtonType;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace FakeDeck.ButtonType
{
internal class FakeDeckMacro : Button
{
public static Dictionary<string, string> actionIcons = new Dictionary<string, string>
{
{ "full-screen", "fa-maximize"},
{ "set-page", "fa-page"},
};
public static string getButton(string Key, string Image = null, string PageId = null, string Color = null)
{
if (Key == "full-screen")
{
return getButtonHTML(actionIcons[Key], Image, Key, null, "!document.fullscreenElement?document.documentElement.requestFullscreen():document.exitFullscreen();", null, Color);
}
if (Key == "set-page")
{
return getButtonHTML(actionIcons[Key], Image, Key, null, "loadPage('"+ PageId + "')", null, Color);
}
if (Key == "spacer")
{
return getButtonHTML(null, null, null, null, null, null, Color);
}
else {
return "NIC";
}
}
}
}

View File

@@ -0,0 +1,106 @@
using FakeDeck.Class;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Net.WebRequestMethods;
namespace FakeDeck.ButtonType
{
class HelldiversTwoMacro : Button
{
const uint Key_Up = 0x68;
const uint Key_Down = 0x62;
const uint Key_Left = 0x64;
const uint Key_Right = 0x66;
//https://helldivers.wiki.gg/wiki/Stratagems
//https://helldivers.fandom.com/wiki/Stratagems_(Helldivers_2)
public static Dictionary<string, uint[]> stratogems = new Dictionary<string, uint[]>
{
//Mission
{ "reinforce", new uint[] { 0x65, Key_Up, Key_Down, Key_Right, Key_Left, Key_Up}},
{ "resupply", new uint[] { 0x65, Key_Down, Key_Down, Key_Up, Key_Right }},
//Support Weapons
{ "anti-material", new uint[] { 0x65, Key_Down, Key_Left, Key_Right, Key_Up, Key_Down}},
{ "flamethrower", new uint[] { 0x65, Key_Down, Key_Left, Key_Up, Key_Down, Key_Up}},
{ "autocannon", new uint[] { 0x65, Key_Down, Key_Left, Key_Down, Key_Up, Key_Up, Key_Right}},
{ "grenade-launcher", new uint[] { 0x65, Key_Down, Key_Left, Key_Up, Key_Left, Key_Down}},
//Offensive: Orbital Strikes
{ "orbital-precision-strike", new uint[] { 0x65, Key_Right, Key_Right, Key_Up}},
{ "orbital-380-barrage", new uint[] { 0x65, Key_Right, Key_Down, Key_Up, Key_Up, Key_Left, Key_Down, Key_Down}},
//Defensive
{ "mortar-sentry", new uint[] { 0x65, Key_Down, Key_Up, Key_Right, Key_Right, Key_Down }},
{ "gatling-sentry", new uint[] { 0x65, Key_Down, Key_Up, Key_Right, Key_Left}},
//Supply: Backpacks
//Offensive: Eagle
{ "strafing-run", new uint[] { 0x65, Key_Up, Key_Right, Key_Right}},
{ "airstrike", new uint[] { 0x65, Key_Up, Key_Right, Key_Down, Key_Right}},
{ "cluster-bomb", new uint[] { 0x65, Key_Up, Key_Right, Key_Down, Key_Down, Key_Right}},
{ "napalm-airstrike", new uint[] { 0x65, Key_Up, Key_Right, Key_Down, Key_Up}},
{ "smoke-strike", new uint[] { 0x65, Key_Up, Key_Right, Key_Up, Key_Down}},
{ "rocket-pods", new uint[] { 0x65, Key_Up, Key_Right, Key_Up, Key_Left}},
{ "bomb", new uint[] { 0x65, Key_Up, Key_Right, Key_Up, Key_Right}},
};
public static Dictionary<string, string> stratogemsIcons = new Dictionary<string, string>
{
{ "reinforce", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/5/5a/HD2_Reinforce.png"},
{ "resupply", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/7/72/HD2_Resupply.png"},
{ "anti-material", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/c/c3/APW-1_Anti-Materiel_Rifle_Icon.png"},
{ "flamethrower", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/c/cc/FLAM-40_Flamethrower_Icon.png"},
{ "autocannon", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/c/c6/AC-8_Autocannon_Icon.png"},
{ "grenade-launcher","https://static.wikia.nocookie.net/helldivers_gamepedia/images/6/66/GL-21_Grenade_Launcher_Icon.png"},
{ "orbital-precision-strike", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/4/47/Orbital_Precision_Strike_Icon.png"},
{ "orbital-380-barrage", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/f/f4/Orbital_380MM_HE_Barrage_Icon.png"},
{ "mortar-sentry", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/1/1d/A_M-12_Mortar_Sentry_Icon.png"},
{ "gatling-sentry","https://static.wikia.nocookie.net/helldivers_gamepedia/images/4/48/A_G-16_Gatling_Sentry_Icon.png"},
//Offensive: Eagle
{ "strafing-run","https://static.wikia.nocookie.net/helldivers_gamepedia/images/3/33/Eagle_Strafing_Run_Icon.png"},
{ "airstrike","https://static.wikia.nocookie.net/helldivers_gamepedia/images/7/7e/Eagle_Airstrike_Icon.png"},
{ "cluster-bomb","https://static.wikia.nocookie.net/helldivers_gamepedia/images/8/89/Eagle_Cluster_Bomb_Icon.png"},
{ "napalm-airstrike","https://static.wikia.nocookie.net/helldivers_gamepedia/images/d/d4/Eagle_Napalm_Airstrike_Icon.png"},
{ "smoke-strike","https://static.wikia.nocookie.net/helldivers_gamepedia/images/1/1a/Eagle_Smoke_Strike_Icon.png"},
{ "rocket-pods","https://static.wikia.nocookie.net/helldivers_gamepedia/images/e/e3/Eagle_110MM_Rocket_Pods_Icon.png"},
{ "bomb","https://static.wikia.nocookie.net/helldivers_gamepedia/images/5/5a/Eagle_500KG_Bomb_Icon.png"},
};
public static string getButton(string Key)
{
return getButtonHTML(null, stratogemsIcons[Key].ToString(), Key, "button\\HelldiversTwoMacro", null, new Dictionary<string, string>() { { "stratogem", Key } });
}
public static bool invokeAction(string stratogem)
{
foreach (var key in stratogems[stratogem])
{
KeyboardMacro.SendKey(key);
Debug.WriteLine(key);
}
return true;
}
private static string FirstLetterToUpper(string str)
{
if (str == null)
return null;
if (str.Length > 1)
return char.ToUpper(str[0]) + str.Substring(1);
return str.ToUpper();
}
}
}

View File

@@ -5,10 +5,12 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace FakeeDeck.ButtonType
namespace FakeDeck.ButtonType
{
internal class KeyboardMacro
{
//https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void keybd_event(uint bVk, uint bScan, uint dwFlags, uint dwExtraInfo);

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FakeeDeck.ButtonType
namespace FakeDeck.ButtonType
{
internal class MediaMacro : Button
{
@@ -12,17 +12,22 @@ namespace FakeeDeck.ButtonType
{
{ "play/pause", new uint[] { 0xB3}},
{ "mute", new uint[] { 0xAD }},
{ "next", new uint[] { 0xB0 }},
{ "previous", new uint[] { 0xB1 }},
};
public static Dictionary<string, string> mediaIcons = new Dictionary<string, string>
{
{ "play/pause", "fa-play"},
{ "mute", "fa-volume-xmark"},
{ "next", "fa-forward"},
{ "previous", "fa-backward"},
};
public static string getButton(string Key)
{
return getButtonHTML(mediaIcons[Key], null, Key, "button\\MediaMacro", new Dictionary<string, string>() { { "control_action", Key } });
return getButtonHTML(mediaIcons[Key], null, Key, "button\\MediaMacro", null, new Dictionary<string, string>() { { "control_action", Key } });
}
public static bool invokeAction(string control_action)

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows;
using static System.Text.Json.JsonElement;
namespace FakeDeck.ButtonType
{
class ProcessMacro : Button
{
public static string getButton(string process, string arguments = "", string? icon = null, string? image = null)
{
Dictionary<string, string> parameters = new Dictionary<string, string>() { { "process", process } };
if (!string.IsNullOrEmpty(arguments))
{
parameters.Add("arguments", arguments);
}
if (!string.IsNullOrEmpty(icon) || !string.IsNullOrEmpty(image))
{
process = null;
}
return getButtonHTML(icon, image, process, "button\\ProcessMacro", null, parameters);
}
public static bool invokeAction(string process, string arguments = "")
{
if (!File.ReadAllText("./configuration.yaml").Contains(process))
{
Debug.WriteLine("not known process");
return false;
}
if (!File.ReadAllText("./configuration.yaml").Contains(arguments))
{
Debug.WriteLine("not known arguments");
return false;
}
Process notePad = new Process();
notePad.StartInfo.FileName = process;
notePad.StartInfo.Arguments = arguments;
notePad.Start();
return true;
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace FakeDeck.Class
{
internal class AbstractionHelper
{
public static Type? resolvType(string className)
{
string cleanClass = "FakeDeck.ButtonType." + className.Trim('/');
Type? buttonClass = Type.GetType(cleanClass, true);
if (buttonClass is null)
return null;
return buttonClass;
}
public static string getButtonVisual(JsonElement button)
{
string calssName = button.GetProperty("function").ToString();
MethodInfo? renderMethod = resolvType(calssName).GetMethod("getButton");
ParameterInfo[] pars = renderMethod.GetParameters();
List<object> parameters = new List<object>();
foreach (ParameterInfo p in pars)
{
JsonElement parameter = button.GetProperty("parameters").EnumerateArray().SingleOrDefault(item => item.GetProperty("name").ToString() == p.Name);
if (string.IsNullOrEmpty(parameter.ToString()))
{
parameters.Insert(p.Position, p.DefaultValue);
continue;
}
parameters.Insert(p.Position, parameter.GetProperty("value").ToString());
}
return renderMethod.Invoke(null, [.. parameters]).ToString();
}
}
}

View File

@@ -0,0 +1,39 @@
using AutoUpdaterDotNET;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http.Json;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows;
namespace FakeDeck.Class
{
public class AutoUpdateHelper
{
public AutoUpdateHelper() {
AutoUpdater.ParseUpdateInfoEvent += AutoUpdaterOnParseUpdateInfoEvent;
AutoUpdater.Synchronous = true;
AutoUpdater.ShowRemindLaterButton = false;
AutoUpdater.ClearAppDirectory = false;
//AutoUpdater.ReportErrors = Debugger.IsAttached;
AutoUpdater.HttpUserAgent = ("FakeDeck-v" + Assembly.GetExecutingAssembly().GetName().Version);
AutoUpdater.Start("https://api.github.com/repos/GamerClassN7/FakeDeck/releases/latest");
}
private void AutoUpdaterOnParseUpdateInfoEvent(ParseUpdateInfoEventArgs args)
{
JsonElement json = JsonDocument.Parse(args.RemoteData).RootElement;
args.UpdateInfo = new UpdateInfoEventArgs
{
CurrentVersion = json.GetProperty("tag_name").ToString().TrimStart('v')+ ".0",
DownloadURL = json.GetProperty("zipball_url").ToString(),
};
Debug.WriteLine("calling Updater");
}
}
}

View File

@@ -0,0 +1,181 @@
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Text.Json;
using System.Windows;
using static System.Text.Json.JsonElement;
namespace FakeDeck.Class
{
internal class FakeDeckMain
{
private static string cachePath = "./cache/";
public static string pageHeader =
"<!DOCTYPE>" +
"<html lang=\"en\">" +
" <head>" +
" <title>HttpListener Example</title>" +
" <meta charset=\"utf-8\">" +
" <meta name = \"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=yes\">" +
" <link href=\"https://yarnpkg.com/en/package/normalize.css\" rel=\"stylesheet\">" +
" <link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css\" rel=\"stylesheet\">" +
" <link href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css\" rel=\"stylesheet\">" +
" <link href=\"StaticFiles/style.css\" rel=\"stylesheet\">" +
" <link rel=\"manifest\" href=\"StaticFiles/manifest.json\" />" +
" </head>" +
" <body>" +
" <div id=\"main\" class=\"d-flex flex-wrap\" style=\"transform-origin: left top;\">";
public static string pageFooter =
" </div>" +
" <script src=\"StaticFiles/app.js\"></script>" +
" </body>" +
"</html>";
public string pageData = "";
private ArrayEnumerator pages;
public FakeDeckMain(YamlHelper yaml)
{
HttpServer server = new HttpServer(yaml.getData().GetProperty("server").GetProperty("port").ToString());
pages = yaml.getData().GetProperty("pages").EnumerateArray();
//ClearCache
if (Directory.Exists(cachePath))
{
DirectoryInfo di = new DirectoryInfo(cachePath);
foreach (FileInfo file in di.EnumerateFiles())
{
file.Delete();
}
}
pageData = renderPageView();
server.addRoute(servViewResponseAsync, "GET", "/");
server.addRoute(servButtonResponseAsync, "POST", "/button/");
server.addRoute(servPageResponseAsync, "POST", "/page");
server.serv();
}
private static void callButtonAction(string module, Dictionary<string, string> postParams)
{
string cleanClass = "FakeDeck.ButtonType." + module.Trim('/');
Type? buttonClass = Type.GetType(cleanClass, true);
if (buttonClass is null)
return;
MethodInfo? method = buttonClass.GetMethod("invokeAction");
if (method is null)
return;
ParameterInfo[] pars = method.GetParameters();
List<object> parameters = new List<object>();
foreach (ParameterInfo p in pars)
{
if (p == null)
{
continue;
}
if (p.Name != null && postParams.ContainsKey(p.Name))
{
parameters.Insert(p.Position, postParams[p.Name]);
}
else if (p.IsOptional && p.DefaultValue != null)
{
parameters.Insert(p.Position, p.DefaultValue);
}
}
_ = method.Invoke(null, [.. parameters]).ToString();
}
private async Task servViewResponseAsync(HttpListenerRequest req, HttpListenerResponse resp)
{
string disableSubmit = false ? "disabled" : "";
byte[] data = Encoding.UTF8.GetBytes(string.Format(pageHeader + this.pageData + pageFooter, 0, disableSubmit));
resp.ContentType = "text/html";
resp.ContentEncoding = Encoding.UTF8;
resp.ContentLength64 = data.LongLength;
await resp.OutputStream.WriteAsync(data, 0, data.Length);
}
private async Task servButtonResponseAsync(HttpListenerRequest req, HttpListenerResponse resp, Dictionary<string, string> postParams)
{
try
{
string module = req.Url.AbsolutePath.Replace("/button", "");
Debug.WriteLine("Call module " + module);
callButtonAction(module, postParams);
resp.StatusCode = (int)HttpStatusCode.OK;
await resp.OutputStream.FlushAsync();
}
catch (Exception ex)
{
byte[] errorData = Encoding.UTF8.GetBytes(ex.Message);
resp.ContentType = "text/html";
resp.ContentEncoding = Encoding.UTF8;
resp.ContentLength64 = errorData.LongLength;
resp.StatusCode = (int)HttpStatusCode.InternalServerError;
await resp.OutputStream.WriteAsync(errorData, 0, errorData.Length);
}
}
private async Task servPageResponseAsync(HttpListenerRequest req, HttpListenerResponse resp, Dictionary<string, string> postParams)
{
string pageContent = "";
try
{
pageContent = renderPageView(postParams["Key"]);
resp.StatusCode = (int)HttpStatusCode.OK;
}
catch (Exception ex)
{
pageContent = ex.Message;
resp.StatusCode = (int)HttpStatusCode.InternalServerError;
}
byte[] errorData = Encoding.UTF8.GetBytes(pageContent);
resp.ContentType = "text/html";
resp.ContentEncoding = Encoding.UTF8;
resp.ContentLength64 = errorData.LongLength;
await resp.OutputStream.WriteAsync(errorData, 0, errorData.Length);
}
private string renderPageView(string page = null)
{
JsonElement selectedPage = pages.First();
if (page != null)
selectedPage = pages.SingleOrDefault(item => item.GetProperty("page").ToString() == page);
string SelectedPageName = selectedPage.GetProperty("page").ToString();
if (File.Exists(cachePath + SelectedPageName + ".html"))
return File.ReadAllText(cachePath + SelectedPageName + ".html");
string pageContent = "";
foreach (JsonElement button in selectedPage.GetProperty("buttons").EnumerateArray())
{
try
{
pageContent += AbstractionHelper.getButtonVisual(button);
}
catch (Exception ex) {
}
}
if (Directory.Exists(cachePath))
Directory.CreateDirectory(cachePath);
File.WriteAllText(cachePath + SelectedPageName + ".html", pageContent);
return pageContent;
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
namespace FakeDeck.Class
{
class GeneralHelper
{
public static BitmapImage BitmapToImageSource(System.Drawing.Bitmap bitmap)
{
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
memory.Position = 0;
BitmapImage bitmapimage = new BitmapImage();
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();
return bitmapimage;
}
}
}
}

View File

@@ -9,7 +9,7 @@ using System.IO;
using System.Text;
using System.Net;
using System.Threading.Tasks;
using FakeeDeck.ButtonType;
using FakeDeck.ButtonType;
using System.Web;
using static System.Net.WebRequestMethods;
using File = System.IO.File;
@@ -17,11 +17,20 @@ using System.Reflection.Metadata;
using System.Xml.Linq;
using System.Reflection;
using System.Text.Json;
using System.Collections;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace FakeeDeck
namespace FakeDeck.Class
{
internal class HttpServer
{
public string port = "8000";
public HttpServer(string port)
{
port = port;
}
private static IDictionary<string, string> mimeTypes = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) {
{".asf", "video/x-ms-asf"},
{".asx", "video/x-ms-asf"},
@@ -47,6 +56,7 @@ namespace FakeeDeck
{".img", "application/octet-stream"},
{".iso", "application/octet-stream"},
{".jar", "application/java-archive"},
{".json", "application/json"},
{".jardiff", "application/x-java-archive-diff"},
{".jng", "image/x-jng"},
{".jnlp", "application/x-java-jnlp-file"},
@@ -88,38 +98,22 @@ namespace FakeeDeck
{".xpi", "application/x-xpinstall"},
{".zip", "application/zip"},
};
private Dictionary<string, Dictionary<string, Delegate>> routes = new Dictionary<string, Dictionary<string, Delegate>>();
public static HttpListener listener;
public static string url = "http://*:8000/";
public static int pageViews = 0;
public static int requestCount = 0;
public static string pageHeader =
"<!DOCTYPE>" +
"<html>" +
" <head>" +
" <title>HttpListener Example</title>" +
" <link href=\"https://yarnpkg.com/en/package/normalize.css\" rel=\"stylesheet\">" +
" <link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css\" rel=\"stylesheet\">" +
" <link href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css\" rel=\"stylesheet\">" +
" </head>" +
" <body>" +
" <div class=\"d-flex flex-wrap\">" +
" <div class=\"m-2\">" +
" <p style=\"margin-bottom: 0px; width: 150px;height: 150px;background-color: aquamarine;\" >Page Views: {0}</p>" +
" </div>";
public static string pageFooter =
" <div class=\"m-2\">" +
" <button style=\"width: 150px;height: 150px;background-color: aquamarine;\" onclick=\"!document.fullscreenElement ? document.documentElement.requestFullscreen() : document.exitFullscreen();\">" +
" <i class=\"fa-solid fa-maximize\"></i>" +
" </button>" +
" </div>" +
" </div>" +
" <script src=\"StaticFiles/app.js\"></script>" +
" </body>" +
"</html>";
public static string pageData = "";
public static async Task HandleIncomingConnections()
public void addRoute(Delegate callback, string method = "GET", string route = "/")
{
if (!routes.ContainsKey(method))
{
routes.Add(method, new Dictionary<string, Delegate>());
}
routes[method].Add(route, callback);
}
public async Task HandleIncomingConnections()
{
bool runServer = true;
@@ -134,76 +128,53 @@ namespace FakeeDeck
HttpListenerResponse resp = ctx.Response;
// Print out some info about the request
Console.WriteLine("Request #: {0}", ++requestCount);
Console.WriteLine(req.Url.ToString());
Console.WriteLine(req.HttpMethod);
Console.WriteLine(req.UserHostName);
Console.WriteLine(req.UserAgent);
Console.WriteLine();
/*Debug.WriteLine("Request #: {0}", ++requestCount);
Debug.WriteLine(req.Url.ToString());
Debug.WriteLine(req.HttpMethod);
Debug.WriteLine(req.UserHostName);
Debug.WriteLine(req.UserAgent);*/
if (req.HttpMethod == "POST")
bool isMatch = false;
if (req.HttpMethod == "GET" && req.Url.AbsolutePath.Contains("."))
{
//Parse Port Parameters
Dictionary<string, string> postParams = parsePostRequestParameters(req);
// If `shutdown` url requested w/ POST, then shutdown the server after serving the page
if (req.Url.AbsolutePath == "/shutdown")
await servFileResponseAsync(req, resp);
}
else
{
foreach (var route in routes[req.HttpMethod])
{
Console.WriteLine("Shutdown requested");
runServer = false;
isMatch = Regex.IsMatch(req.Url.AbsolutePath, route.Key, RegexOptions.IgnoreCase);
if (isMatch)
{
Debug.WriteLine(route.Key);
Delegate gelegate = route.Value;
if (req.HttpMethod == "POST")
{
Dictionary<string, string> postParams = parsePostRequestParameters(req);
gelegate.DynamicInvoke([req, resp, postParams]);
break;
}
gelegate.DynamicInvoke([req, resp]);
break;
}
}
else if (req.Url.AbsolutePath.StartsWith("/button"))
if (!isMatch)
{
try
{
string module = req.Url.AbsolutePath.Replace("/button", "");
Console.WriteLine("Call module " + module);
callButtonAction(module, postParams);
resp.StatusCode = (int)HttpStatusCode.OK;
}
catch (Exception ex)
{
byte[] errorData = Encoding.UTF8.GetBytes(ex.Message);
resp.ContentType = "text/html";
resp.ContentEncoding = Encoding.UTF8;
resp.ContentLength64 = errorData.LongLength;
resp.StatusCode = (int)HttpStatusCode.InternalServerError;
await resp.OutputStream.WriteAsync(errorData, 0, errorData.Length);
}
finally
{
resp.Close();
}
continue;
Debug.WriteLine("NO ROUTE MATCHED");
resp.StatusCode = (int)HttpStatusCode.NotFound;
await resp.OutputStream.FlushAsync();
}
}
else if (req.HttpMethod == "GET")
{
if (req.Url.AbsolutePath.Contains("."))
{
await servFileResponseAsync(req, resp);
}
else
{
await servViewResponseAsync(req, resp);
}
resp.Close();
continue;
}
resp.Close();
}
}
public static void serv()
public void serv()
{
foreach (var stratogem in HelldiversTwoMacro.stratogems)
{
pageData += HelldiversTwoMacro.getButton(stratogem.Key);
}
foreach (var control in MediaMacro.mediaControls)
{
pageData += MediaMacro.getButton(control.Key);
}
string url = "http://*:" + port + "/";
// Create a Http server and start listening for incoming connections
listener = new HttpListener();
listener.Prefixes.Add(url);
@@ -218,50 +189,14 @@ namespace FakeeDeck
listener.Close();
}
private static void callButtonAction(string module, Dictionary<string, string> postParams)
{
string cleanClass = "FakeeDeck.ButtonType." + module.Trim('/');
Type? buttonClass = Type.GetType(cleanClass, true);
if (buttonClass is null)
return;
MethodInfo? method = buttonClass.GetMethod("invokeAction");
if (method is null)
return;
ParameterInfo[] pars = method.GetParameters();
List<object> parameters = new List<object>();
foreach (ParameterInfo p in pars)
{
if (p == null)
{
continue;
}
if (p.Name != null && postParams.ContainsKey(p.Name))
{
parameters.Insert(p.Position, postParams[p.Name]);
}
else if (p.IsOptional && p.DefaultValue != null)
{
parameters.Insert(p.Position, p.DefaultValue);
}
}
_ = method.Invoke(null, [.. parameters]).ToString();
}
private static async Task servFileResponseAsync(HttpListenerRequest req, HttpListenerResponse resp)
{
string filename = Path.Combine("./", req.Url.AbsolutePath.Substring(1));
if (!File.Exists(filename))
{
resp.StatusCode = (int)HttpStatusCode.NotFound;
resp.Close();
resp.OutputStream.Flush();
return;
}
try
@@ -281,9 +216,8 @@ namespace FakeeDeck
while ((nbytes = input.Read(buffer, 0, buffer.Length)) > 0)
resp.OutputStream.Write(buffer, 0, nbytes);
input.Close();
resp.OutputStream.Flush();
resp.StatusCode = (int)HttpStatusCode.OK;
resp.OutputStream.Flush();
}
catch (Exception ex)
{
@@ -296,16 +230,6 @@ namespace FakeeDeck
}
}
private static async Task servViewResponseAsync(HttpListenerRequest req, HttpListenerResponse resp)
{
string disableSubmit = false ? "disabled" : "";
byte[] data = Encoding.UTF8.GetBytes(String.Format((pageHeader + pageData + pageFooter), pageViews, disableSubmit));
resp.ContentType = "text/html";
resp.ContentEncoding = Encoding.UTF8;
resp.ContentLength64 = data.LongLength;
await resp.OutputStream.WriteAsync(data, 0, data.Length);
}
private static Dictionary<string, string> parsePostRequestParameters(HttpListenerRequest req)
{
Dictionary<string, string> postParams = new Dictionary<string, string>();

View File

@@ -4,9 +4,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FakeeDeck.Class
namespace FakeDeck.Class
{
internal class Keyboard
internal class KeyboardCode
{
public const uint LBUTTON = 0x01; // Left mouse button
public const uint RBUTTON = 0x02; // Right mouse button

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using YamlDotNet.Serialization;
namespace FakeDeck.Class
{
public class YamlHelper
{
JsonDocument jsonObjecz;
public YamlHelper()
{
var r = new StreamReader("./configuration.yaml");
var deserializer = new Deserializer();
object yamlObject = deserializer.Deserialize(r);
string json = System.Text.Json.JsonSerializer.Serialize(yamlObject);
jsonObjecz = JsonDocument.Parse(json);
}
public JsonElement getData()
{
return jsonObjecz.RootElement;
}
}
}

View File

@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Autoupdater.NET.Official" Version="1.9.2" />
<PackageReference Include="QRCoder" Version="1.6.0" />
<PackageReference Include="YamlDotNet" Version="16.1.0" />
</ItemGroup>
<ItemGroup>
<None Update="configuration.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="StaticFiles\app.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="StaticFiles\manifest.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="StaticFiles\style.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,20 @@
<Window x:Name="FakeDeckUI" x:Class="FakeDeck.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FakeDeck"
mc:Ignorable="d"
Title="MainWindow"
Activated="FakeDeckUI_Activated"
WindowStartupLocation="CenterScreen"
Width="280" Height="340">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="270"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<Image x:Name="qr_code" Margin="10,10,10,0"/>
<TextBox Margin="10,10,10,10" TextWrapping="Wrap" Text="TextBox" Grid.Row="1" Height="20" VerticalAlignment="Center"/>
</Grid>
</Window>

View File

@@ -0,0 +1,56 @@
using FakeDeck.Class;
using FakeDeck.Class;
using QRCoder;
using System.Reflection.Emit;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static QRCoder.QRCodeGenerator;
using static System.Runtime.CompilerServices.RuntimeHelpers;
using System.Drawing;
using Color = System.Drawing.Color;
using AutoUpdaterDotNET;
using System.Diagnostics;
namespace FakeDeck
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void FakeDeckUI_Activated(object sender, EventArgs e)
{
string port = ((App)Application.Current).yaml.getData().GetProperty("server").GetProperty("port").ToString();
string url = "http://localhost:" + port;
PayloadGenerator.Url qrCodePayload = new PayloadGenerator.Url(url);
QRCodeGenerator qrCodeGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrCodeGenerator.CreateQrCode(qrCodePayload.ToString(), 0);
QRCode qrCode = new QRCode(qrCodeData);
qr_code.Source = GeneralHelper.BitmapToImageSource(qrCode.GetGraphic(20, Color.Black, Color.White, false));
try
{
AutoUpdateHelper updater = new AutoUpdateHelper();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
}

View File

@@ -0,0 +1,108 @@
function urlencodeFormData(fd){
var s = '';
function encode(s){ return encodeURIComponent(s).replace(/%20/g,'+'); }
for(var pair of fd.entries()){
if(typeof pair[1]=='string'){
s += (s?'&':'') + encode(pair[0])+'='+encode(pair[1]);
}
}
return s;
}
function resizeGrid(){
var width = document.body.clientWidth;
var height = document.body.clientHeight;
width = window.screen.availWidth;
height = window.screen.availHeight;
var biggerSizeW = (width / 7);
var biggerSizeH = (height / 5);
var biggerSize = biggerSizeW;
if(biggerSizeW < biggerSizeH){
biggerSize = biggerSizeW;
}
console.log(biggerSize);
[].forEach.call(document.querySelectorAll('.button'), function (button) {
var size = biggerSize
button.style.height = size;
button.style.width = size;
//console.log(size);
});
}
function loadPage(pageId){
event.preventDefault();
var formData = new FormData();
formData.append('Key', pageId)
const xhttp = new XMLHttpRequest();
xhttp.onload = function () { }
xhttp.onreadystatechange = function () {
if (xhttp.readyState === 4) {
if (xhttp.status === 200) {
console.log('successful');
document.querySelector('div#main').innerHTML = xhttp.responseText;
console.log(xhttp.responseText);
resizeGrid();
formToAjax();
} else {
console.log('failed');
}
}
}
xhttp.open("POST", "/page", true);
xhttp.send(urlencodeFormData(formData));
}
function formToAjax(){
[].forEach.call(document.querySelectorAll('form'), function (form) {
form.addEventListener('submit', function (event) {
event.preventDefault();
const target = event.currentTarget;
target.style.opacity = "0.5"
navigator.vibrate(200);
console.log(target.method, target.action);
console.log(form.method, form.action);
console.log(form === target);
var formData = new FormData(form);
const xhttp = new XMLHttpRequest();
xhttp.onload = function () { }
xhttp.onreadystatechange = function () {
if (xhttp.readyState === 4) {
if (xhttp.status === 200) {
console.log('successful');
} else {
console.log('failed');
}
target.style.opacity = "1"
}
}
xhttp.open(target.method, target.action, true);
xhttp.send(urlencodeFormData(formData));
});
});
}
window.addEventListener('resize', function(event) {
resizeGrid();
}, true);
window.addEventListener('orientationchange', function(event) {
console.log("Rotated");
resizeGrid();
}, true);
resizeGrid();
formToAjax();

View File

@@ -0,0 +1,10 @@
{
"name": "FakeDeck",
"short_name": "FakeDeck",
"theme_color": "#fff",
"background_color": "#fff",
"display": "fullscreen",
"orientation": "landscape",
"scope": "/",
"start_url": "/"
}

View File

@@ -0,0 +1 @@
/*https://stackoverflow.com/questions/62371077/create-dynamic-equal-sized-small-squares-grid-in-fixed-size-big-square/

View File

@@ -0,0 +1,248 @@
server:
port: 8000
pages:
- page: helldivers
buttons:
- button: reinforce
function: HelldiversTwoMacro
parameters:
- name: Key
value: "reinforce"
- button: flamethrower
function: HelldiversTwoMacro
parameters:
- name: Key
value: "flamethrower"
- button: anti-material
function: HelldiversTwoMacro
parameters:
- name: Key
value: "anti-material"
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: red
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: red
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: red
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: red
- button: strafing-run
function: HelldiversTwoMacro
parameters:
- name: Key
value: strafing-run
- button: airstrike
function: HelldiversTwoMacro
parameters:
- name: Key
value: airstrike
- button: cluster-bomb
function: HelldiversTwoMacro
parameters:
- name: Key
value: cluster-bomb
- button: napalm-airstrike
function: HelldiversTwoMacro
parameters:
- name: Key
value: napalm-airstrike
- button: smoke-strike
function: HelldiversTwoMacro
parameters:
- name: Key
value: smoke-strike
- button: rocket-pods
function: HelldiversTwoMacro
parameters:
- name: Key
value: rocket-pods
- button: bomb
function: HelldiversTwoMacro
parameters:
- name: Key
value: bomb
- button: full-screen
function: FakeDeckMacro
parameters:
- name: Key
value: "full-screen"
- name: Color
value: orange
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: orange
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: red
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: red
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: red
- button: orbital-380-barrage
function: HelldiversTwoMacro
parameters:
- name: Key
value: orbital-380-barrage
- button: page
function: FakeDeckMacro
parameters:
- name: Key
value: "set-page"
- name: PageId
value: "media"
- name: Image
value: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTdEjIsQcn8NwYWhwISL74xXLGtRHeW1Mn67g&s"
- page: media
buttons:
- button: notepad
function: ProcessMacro
parameters:
- name: process
value: "notepad.exe"
- name: image
value: "https://www.club386.com/wp-content/uploads/2021/12/notepad-icon-696x632.jpg"
- button: cmd
function: ProcessMacro
parameters:
- name: process
value: "cmd.exe"
- name: arguments
value: "/C ping google.com -t"
- name: image
value: "https://winaero.com/blog/wp-content/uploads/2019/06/WIndows-Terminal-icon.png"
- button: mute
function: MediaMacro
parameters:
- name: Key
value: "mute"
- button: mute
function: MediaMacro
parameters:
- name: Key
value: "previous"
- button: mute
function: MediaMacro
parameters:
- name: Key
value: "play/pause"
- button: mute
function: MediaMacro
parameters:
- name: Key
value: "next"
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "full-screen"
- name: Color
value: orange
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: red
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: red
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: red
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: "spacer"
- name: Color
value: red
- button: page
function: FakeDeckMacro
parameters:
- name: Key
value: "set-page"
- name: PageId
value: "helldivers"
- name: Image
value: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT2oyk6yqmBxt9ejwqBaordr6X9s-dZFnHrvg&s"

View File

@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.11.35219.272
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FakeeDeck", "FakeeDeck\FakeeDeck.csproj", "{D8C79B08-1920-426A-9138-CF0C8BAE0EF7}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FakeDeck", "FakeDeckUI\FakeDeck\FakeDeck.csproj", "{D04AFC99-A929-4336-BD2C-1D49D149DB18}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -11,10 +11,10 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D8C79B08-1920-426A-9138-CF0C8BAE0EF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D8C79B08-1920-426A-9138-CF0C8BAE0EF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8C79B08-1920-426A-9138-CF0C8BAE0EF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8C79B08-1920-426A-9138-CF0C8BAE0EF7}.Release|Any CPU.Build.0 = Release|Any CPU
{D04AFC99-A929-4336-BD2C-1D49D149DB18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D04AFC99-A929-4336-BD2C-1D49D149DB18}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D04AFC99-A929-4336-BD2C-1D49D149DB18}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D04AFC99-A929-4336-BD2C-1D49D149DB18}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FakeeDeck.ButtonType
{
internal class Button
{
public static string getButtonHTML(string icon, string image, string name, string action, Dictionary<string, string> parameters = null)
{
string body = "";
body += "<div class=\"m-2\">";
body += "<form style=\"margin-bottom: 0px;\" method=\"post\" action=\"" + action + "\">";
if (parameters is not null)
{
foreach (var parameter in parameters)
{
body += "<input type=\"hidden\" name=\"" + parameter.Key + "\" value=\"" + parameter.Value + "\">";
}
}
body += "<button type=\"submit\" value=\"submit\" style=\"background-size: cover; " + (!string.IsNullOrEmpty(image) ? "background-image: url('" + image + "');" : "") + " width: 150px;height: 150px; background-color: aquamarine;\" >";
body += (!string.IsNullOrEmpty(icon) ? "<i class=\"fa-solid " + icon + "\"></i>" : name);
body += "</button>";
body += "</form>";
body += "</div>";
return body;
}
public static string getButton(string Key)
{
return getButtonHTML(null, "https://docs.itego.cz/uploads/images/system/2022-04/OdRTPJ4iTTInmhdP-jagq7dfjpi2lilfg-imageedit-2-6604933313.gif", "Test", "test/test");
}
public static bool invokeAction(string Key)
{
return false;
}
}
}

View File

@@ -1,77 +0,0 @@
using FakeeDeck.Class;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Net.WebRequestMethods;
namespace FakeeDeck.ButtonType
{
class HelldiversTwoMacro : Button
{
//https://helldivers.wiki.gg/wiki/Stratagems
//https://helldivers.fandom.com/wiki/Stratagems_(Helldivers_2)
public static Dictionary<string, uint[]> stratogems = new Dictionary<string, uint[]>
{
{ "reinforce", new uint[] { 0x65, 0x68, 0x62, 0x66, 0x64, 0x68}},
{ "resupply", new uint[] { 0x65, 0x62, 0x62, 0x68, 0x66 }},
//Patriotic Administration Center
{ "anti-material", new uint[] { 0x65, 0x62, 0x64, 0x66, 0x68, 0x62}},
{ "flamethrower", new uint[] { 0x65, 0x62, 0x64, 0x68, 0x62, 0x68}},
{ "autocannon", new uint[] { 0x65, 0x62, 0x64, 0x62, 0x68, 0x68, 0x66}},
{ "grenade-launcher", new uint[] { 0x65, 0x62, 0x64, 0x68, 0x64, 0x62}},
//Orbital Cannons
{ "orbital-precision-strike", new uint[] { 0x65, 0x66, 0x66, 0x68}},
//Robotics Workshop
{ "mortar-sentry", new uint[] { 0x65, 0x62, 0x68, 0x66, 0x62}},
{ "gatling-sentry", new uint[] { 0x65, 0x62, 0x68, 0x66, 0x64}},
//Hangar
{ "rocket-pods", new uint[] { 0x65, 0x68, 0x66, 0x68, 0x64}},
{ "bomb", new uint[] { 0x65, 0x68, 0x66, 0x68, 0x64}},
};
public static Dictionary<string, string> stratogemsIcons = new Dictionary<string, string>
{
{ "reinforce", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/5/5a/HD2_Reinforce.png"},
{ "resupply", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/7/72/HD2_Resupply.png"},
{ "anti-material", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/c/c3/APW-1_Anti-Materiel_Rifle_Icon.png"},
{ "flamethrower", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/c/cc/FLAM-40_Flamethrower_Icon.png"},
{ "autocannon", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/c/c6/AC-8_Autocannon_Icon.png"},
{ "grenade-launcher","https://static.wikia.nocookie.net/helldivers_gamepedia/images/6/66/GL-21_Grenade_Launcher_Icon.png"},
{ "orbital-precision-strike", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/4/47/Orbital_Precision_Strike_Icon.png"},
{ "mortar-sentry", "https://static.wikia.nocookie.net/helldivers_gamepedia/images/1/1d/A_M-12_Mortar_Sentry_Icon.png"},
{ "gatling-sentry","https://static.wikia.nocookie.net/helldivers_gamepedia/images/4/48/A_G-16_Gatling_Sentry_Icon.png"},
{ "rocket-pods","https://static.wikia.nocookie.net/helldivers_gamepedia/images/e/e3/Eagle_110MM_Rocket_Pods_Icon.png"},
{ "bomb","https://static.wikia.nocookie.net/helldivers_gamepedia/images/5/5a/Eagle_500KG_Bomb_Icon.png"},
};
public static string getButton(string Key)
{
return getButtonHTML(null, stratogemsIcons[Key].ToString(), Key, "button\\HelldiversTwoMacro", new Dictionary<string, string>() { { "stratogem", Key } });
}
public static bool invokeAction(string stratogem)
{
foreach (var key in stratogems[stratogem])
{
KeyboardMacro.SendKey(key);
Console.WriteLine(key);
}
return true;
}
private static string FirstLetterToUpper(string str)
{
if (str == null)
return null;
if (str.Length > 1)
return char.ToUpper(str[0]) + str.Substring(1);
return str.ToUpper();
}
}
}

View File

@@ -1,20 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="StaticFiles\" />
</ItemGroup>
<ItemGroup>
<None Update="StaticFiles\app.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -1,3 +0,0 @@
using FakeeDeck;
HttpServer.serv();

View File

@@ -1,38 +0,0 @@
[].forEach.call(document.querySelectorAll('form'), function (form) {
form.addEventListener('submit', function (event) {
event.preventDefault();
const target = event.currentTarget;
console.log(target.method, target.action);
console.log(form.method, form.action);
console.log(form === target);
var formData = new FormData(form);
const xhttp = new XMLHttpRequest();
xhttp.onload = function () { }
xhttp.onreadystatechange = function () {
if (xhttp.readyState === 4) {
if (xhttp.status === 200) {
console.log('successful');
} else {
console.log('failed');
}
}
}
xhttp.open(target.method, target.action, true);
xhttp.send(urlencodeFormData(formData));
});
});
function urlencodeFormData(fd){
var s = '';
function encode(s){ return encodeURIComponent(s).replace(/%20/g,'+'); }
for(var pair of fd.entries()){
if(typeof pair[1]=='string'){
s += (s?'&':'') + encode(pair[0])+'='+encode(pair[1]);
}
}
return s;
}

154
README.md
View File

@@ -1,5 +1,153 @@
## FakeDeck - Poor Man Macro Pad
<div align="center">
<img style="border-radius:10px" src="images/logo.png" title="Logo"><br>
<img src="https://img.shields.io/github/downloads/GamerClassN7/FakeDeck/total.svg" alt="Github All Releases">
</div>
Creates simple webserver with buttons whitch can be opened on any device an can be used as macro pad/ keyboard
# FakeDeck - Poor Man Macro Pad
![alt text](images/image.png)
Creates simple webserver with buttons whitch can be opened on any device an can be used as macro pad/keyboard
![alt text](images/image.png)
## How to use it ?
Just add desired macros to `configuration.yaml` and start the application, tahn zou can load dashboard on any web capable device inside of your network.
## Example Macros:
### Helldivers 2 Macros
```yaml
- button: reinforce
function: HelldiversTwoMacro
parameters:
- name: Key
value: reinforce
```
```yaml
- button: strafing-run
function: HelldiversTwoMacro
parameters:
- name: Key
value: strafing-run
```
```yaml
- button: airstrike
function: HelldiversTwoMacro
parameters:
- name: Key
value: airstrike
```
```yaml
- button: cluster-bomb
function: HelldiversTwoMacro
parameters:
- name: Key
value: cluster-bomb
```
```yaml
- button: napalm-airstrike
function: HelldiversTwoMacro
parameters:
- name: Key
value: napalm-airstrike
```
```yaml
- button: smoke-strike
function: HelldiversTwoMacro
parameters:
- name: Key
value: smoke-strike
```
```yaml
- button: rocket-pods
function: HelldiversTwoMacro
parameters:
- name: Key
value: rocket-pods
```
```yaml
- button: bomb
function: HelldiversTwoMacro
parameters:
- name: Key
value: bomb
```
### Media Control Macros
```yaml
- button: mute
function: MediaMacro
parameters:
- name: Key
value: mute
```
```yaml
- button: previous
function: MediaMacro
parameters:
- name: Key
value: previous
```
```yaml
- button: play
function: MediaMacro
parameters:
- name: Key
value: play/pause
```
```yaml
- button: next
function: MediaMacro
parameters:
- name: Key
value: next
```
### FakeDeck UI Control Macros
```yaml
- button: full-screen
function: FakeDeckMacro
parameters:
- name: Key
value: full-screen
```
```yaml
- button: set-page
function: FakeDeckMacro
parameters:
- name: Key
value: set-page
- name: PageId
value: {{page-id}}
```
```yaml
- button: spacer
function: FakeDeckMacro
parameters:
- name: Key
value: spacer
```
### Process Macro
```yaml
- button: cmd
function: ProcessMacro
parameters:
- name: process
value: "cmd.exe"
- name: arguments #Optional Proces Arguments
value: "/C ipconfig"
```
### Comon Macro Parameters
```yaml
...
parameters:
- name: Color
value: White #CSS friendly color
- name: Image
value: White #URL To Image (Local Path is not supported now)
...
```
## Contributors
<a href="https://github.com/GamerClassN7/FakeDeck/graphs/contributors">
<img src="https://contrib.rocks/image?repo=GamerClassN7/FakeDeck" />
</a>
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=GamerClassN7/FakeDeck&type=Timeline)](https://star-history.com/#GamerClassN7/FakeDeck&Timeline)]

BIN
images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB