Skip to content

Commit 129205c

Browse files
committed
First Commit
0 parents  commit 129205c

File tree

20 files changed

+4833
-0
lines changed

20 files changed

+4833
-0
lines changed

.gitignore

Whitespace-only changes.

.vscode/settings.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"files.associations": {
3+
"strings.h": "c",
4+
"string.h": "c"
5+
},
6+
"workbench.colorCustomizations": {
7+
"activityBar.activeBackground": "#8375d1",
8+
"activityBar.background": "#8375d1",
9+
"activityBar.foreground": "#15202b",
10+
"activityBar.inactiveForeground": "#15202b99",
11+
"activityBarBadge.background": "#e7bfb7",
12+
"activityBarBadge.foreground": "#15202b",
13+
"commandCenter.border": "#e7e7e799",
14+
"sash.hoverBorder": "#8375d1",
15+
"statusBar.background": "#604fc4",
16+
"statusBar.foreground": "#e7e7e7",
17+
"statusBarItem.hoverBackground": "#8375d1",
18+
"statusBarItem.remoteBackground": "#604fc4",
19+
"statusBarItem.remoteForeground": "#e7e7e7",
20+
"titleBar.activeBackground": "#604fc4",
21+
"titleBar.activeForeground": "#e7e7e7",
22+
"titleBar.inactiveBackground": "#604fc499",
23+
"titleBar.inactiveForeground": "#e7e7e799"
24+
},
25+
"peacock.color": "#604fc4"
26+
}

Initial Version/server_v1.js

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
2+
/////////////////////// Works Fine for Listening Keyboard Inputs ///////////////////////
3+
4+
// const readline = require('readline');
5+
6+
// readline.emitKeypressEvents(process.stdin);
7+
// process.stdin.setRawMode(true);
8+
9+
// process.stdin.on('keypress', (str, key) => {
10+
// console.log(str)
11+
// console.log(key)
12+
// })
13+
14+
////////////////////////////////////////////////////////////////////////////////////////
15+
16+
//const sendkeys = require("sendkeys-js");
17+
18+
//// for win
19+
//setInterval(() => {sendkeys.send('{right}')}, 1000);
20+
21+
////////////////////////////////////////////////////////////////////////////////////////
22+
23+
const express = require("express");
24+
const ws = require("ws");
25+
const screenshot = require('screenshot-desktop')
26+
const imageProcessor = require("sharp");
27+
const operatingSystem = require("os");
28+
const { readFileSync } = require("fs");
29+
const { exec, execFile } = require("child_process");
30+
const path = require("path");
31+
const { json, response } = require("express");
32+
33+
let networkInterfaceDetails = operatingSystem.networkInterfaces();
34+
let computerName = operatingSystem.hostname();
35+
36+
const httpConfig =
37+
{
38+
portNumber: null,
39+
ipAddress: null
40+
};
41+
42+
const webSocketConfig =
43+
{
44+
portNumber: null,
45+
ipAddress: null
46+
};
47+
48+
let userConfig;
49+
userConfig = JSON.parse(readFileSync(path.join(__dirname, "user_config.json"), "utf8"));
50+
console.log("User Config Loaded!");
51+
userConfig["computerName"] = computerName;
52+
console.log(userConfig);
53+
54+
httpConfig.port = userConfig.httpPortNumber;
55+
webSocketConfig.port = userConfig.webSocketPortNumber;
56+
57+
if (userConfig.WiFi == true)
58+
{
59+
httpConfig.ipAddress = networkInterfaceDetails["Wi-Fi"][1]["address"];
60+
webSocketConfig.ipAddress = networkInterfaceDetails["Wi-Fi"][1]["address"];
61+
}
62+
else
63+
{
64+
let networkInterfaceDetails = operatingSystem.networkInterfaces();
65+
httpConfig.ipAddress = networkInterfaceDetails["eth0"][1]["address"];
66+
webSocketConfig.ipAddress = networkInterfaceDetails["eth0"][1]["address"];
67+
}
68+
69+
const server = express();
70+
server.use(express.json({limit: "500kb"}));
71+
server.use(express.static(path.join(__dirname, "assets/public")));
72+
73+
server.listen(httpConfig.port, httpConfig.ipAddress, () =>
74+
{
75+
console.log("Server listening on...");
76+
console.log("Port: ", httpConfig.port);
77+
console.log("IP: ", httpConfig.ipAddress);
78+
});
79+
80+
server.get("/api/get-user-config", (request, response) =>
81+
{
82+
response.json(userConfig);
83+
console.log("Shared User Config!");
84+
});
85+
86+
server.get("/api/get-screenshot", (request, response) =>
87+
{
88+
response.json(screenShotObject);
89+
console.log("Sharing Screenshot!");
90+
});
91+
92+
let isVolumeMeterOpened = false;
93+
94+
server.get("/api/get-volume", (request, response) =>
95+
{
96+
let currentVolumeObject =
97+
{
98+
volume: null
99+
}
100+
if (isVolumeMeterOpened == false)
101+
{
102+
exec("sndvol.exe -f", () =>
103+
{
104+
console.log("Opened Volume Level!");
105+
isVolumeMeterOpened = true;
106+
});
107+
}
108+
109+
execFile(path.join(__dirname, "assets/volume_settings_win/volume_settings_win.exe"), (error, stdout, stderr) =>
110+
{
111+
currentVolumeObject.volume = stdout
112+
response.json(currentVolumeObject);
113+
console.log("Shared Current Volume!");
114+
});
115+
116+
});
117+
118+
server.post("/api/emulate-keys", (request, response) =>
119+
{
120+
console.log(request.body);
121+
const keyboardInputCode = request.body.keyboardInputCode;
122+
console.log(keyboardInputCode);
123+
execFile((path.join(__dirname, "assets/emulate_keys_win/emulate_keys_win.exe")), [keyboardInputCode], (error, stdout, stderr) =>
124+
{
125+
console.log(stdout);
126+
response.json("Input Emulated!");
127+
console.log("Input Emulated!");
128+
});
129+
130+
});
131+
132+
const webSocketServer = new ws.Server({port: webSocketConfig.port, host: webSocketConfig.ipAddress});
133+
134+
webSocketServer.on('connection', (webSocket) =>
135+
{
136+
webSocket.on('message', (data) =>
137+
{
138+
let keyboardInputCode = JSON.parse(data).keyboardInputCode;
139+
console.log(keyboardInputCode);
140+
execFile((path.join(__dirname, "assets/emulate_keys_win/emulate_keys_win.exe")), [keyboardInputCode]);
141+
webSocket.send("Input Emulated!");
142+
console.log("Input Emulated!");
143+
});
144+
145+
webSocket.send('Connection Successful!');
146+
});
147+
148+
149+
screenShotObject =
150+
{
151+
imgInBase64: ""
152+
};
153+
154+
async function screenShotAndResize()
155+
{
156+
const imgBuffer = await screenshot({format: 'png'});
157+
const imgBufferResized = await imageProcessor(imgBuffer).resize(265, 150).png().toBuffer(); // 265x150 resolution does
158+
screenShotObject.imgInBase64 = Buffer.from(imgBufferResized).toString("base64"); // have 16x9 ratio.
159+
//console.log("Image Resized!");
160+
}
161+
162+
setInterval(() => {screenShotAndResize()}, 300);
163+
164+
165+
166+
167+
168+
//const keyboardInputChar = "D";
169+
//const child = execFile('.\\emulate_keyboard.exe', [keyboardInputChar]);
170+
//console.log("${keyboardInputChar}");
171+
//const child = execFile('.\\emulate_keyboard.exe', [`${keyboardInputChar}`]); // Using String Literal notation. Just an alternative.

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Hizbullah Khan
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Computer Remote Control
2+
3+
### Docs to be added soon...
53.9 KB
Binary file not shown.

assets/public/index.html

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
6+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
7+
<title>Remote-Keyboard</title>
8+
<link href="styles.css" rel="stylesheet">
9+
<!--<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>-->
10+
<script src="vue.global.prod.js"></script>
11+
</head>
12+
<!--<body class="body-class dark-mode">-->
13+
<body class="body-class" id="body-ID">
14+
<div class="root" id="root-ID">
15+
<div class="page-routes" v-if="isOptionsButtonPressed == false">
16+
<div class="title-window">
17+
<h2 class="title-text">{{ appConfig.titleText }}</h2>
18+
<h4 class="author-text">@hizbi-github</h4>
19+
<div class="server-status-window">
20+
<div class="connection-status-div-button-window">
21+
<div id="connection-status-div-button" class="connection-status-div-button" v-bind:class="(appConfig.darkMode == 'on') ? 'connection-status-button-dark-mode' : 'connection-status-button-light-mode'" @click="connectDisconnectFromServer(), provideHapticFeedback()">Disconnect</div>
22+
</div>
23+
<div class="server-name-text">{{ appConfig.serverName }}</div>
24+
</div>
25+
</div>
26+
27+
<div class="text-window-and-screenshot">
28+
<div class="text-window">
29+
<div class="log-window" v-bind:class="(appConfig.darkMode == 'on') ? 'dark-mode' : 'light-mode'">
30+
<ul v-html="logList">
31+
</ul>
32+
</div>
33+
34+
<div class="status-window" v-bind:class="(appConfig.darkMode == 'on') ? 'dark-mode' : 'light-mode'">
35+
<div class="status-row">
36+
<div class="status-title">Latency: </div>
37+
<div>{{ latency }}</div>
38+
</div>
39+
<div class="status-row">
40+
<div class="status-title">Volume: </div>
41+
<div>{{ currentVolume }}</div>
42+
</div>
43+
<button class="configuration-page-button" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="renderConfigurationScreen(), provideHapticFeedback()">Settings</button>
44+
</div>
45+
</div>
46+
47+
<div class="screenshot-window-and-screenshot-buttons">
48+
<div class="screenshot-window" v-bind:class="(appConfig.darkMode == 'on') ? 'dark-mode' : 'light-mode'">
49+
<img class="screenshot-img" v-bind:src="imgScreenshot">
50+
</div>
51+
52+
<div class="screenshot-buttons-window" v-bind:class="(appConfig.darkMode == 'on') ? 'dark-mode' : 'light-mode'">
53+
<button class="screenshot-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="showHiResScreenShot(), provideHapticFeedback()">Hi-Res Snap</button>
54+
<button class="screenshot-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="showHideScreenShot(), provideHapticFeedback()">{{ showHideScreenShotButtonText }}</button>
55+
</div>
56+
</div>
57+
</div>
58+
59+
<div class="volume-slider-window">
60+
<input class="volume-slider" type="range">
61+
</div>
62+
63+
<div class="input-buttons-window">
64+
<div class="left-buttons-window">
65+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('leftKeyOne'), provideHapticFeedback()">{{ appConfig.leftKeyOne[0] }}</button>
66+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('leftKeyTwo'), provideHapticFeedback()">{{ appConfig.leftKeyTwo[0] }}</button>
67+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('leftKeyThree'), provideHapticFeedback()">{{ appConfig.leftKeyThree[0] }}</button>
68+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('leftKeyFour'), provideHapticFeedback()">{{ appConfig.leftKeyFour[0] }}</button>
69+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('leftKeyFive'), provideHapticFeedback()">{{ appConfig.leftKeyFive[0] }}</button>
70+
</div>
71+
72+
<div class="middle-buttons-window">
73+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('leftKeyOne'), provideHapticFeedback()">{{ appConfig.leftKeyOne[0] }}</button>
74+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('leftKeyTwo'), provideHapticFeedback()">{{ appConfig.leftKeyTwo[0] }}</button>
75+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('leftKeyThree'), provideHapticFeedback()">{{ appConfig.leftKeyThree[0] }}</button>
76+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('leftKeyFour'), provideHapticFeedback()">{{ appConfig.leftKeyFour[0] }}</button>
77+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('leftKeyFive'), provideHapticFeedback()">{{ appConfig.leftKeyFive[0] }}</button>
78+
</div>
79+
80+
<div class="right-buttons-window">
81+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('rightKeyOne'), provideHapticFeedback()">{{ appConfig.rightKeyOne[0] }}</button>
82+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('rightKeyTwo'), provideHapticFeedback()">{{ appConfig.rightKeyTwo[0] }}</button>
83+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('rightKeyThree'), provideHapticFeedback()">{{ appConfig.rightKeyThree[0] }}</button>
84+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('rightKeyFour'), provideHapticFeedback()">{{ appConfig.rightKeyFour[0] }}</button>
85+
<button class="input-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="emulateKey('rightKeyFive'), provideHapticFeedback()">{{ appConfig.rightKeyFive[0] }}</button>
86+
</div>
87+
</div>
88+
</div>
89+
90+
<div v-if="isOptionsButtonPressed == true">
91+
<div class="title-window">
92+
<h2 class="title-text">Settings</h2>
93+
<h4 class="author-text">@hizbi-github</h4>
94+
<div class="server-status-window">
95+
<div class="connection-status-div-button-window">
96+
<div id="connection-status-div-button" class="connection-status-div-button" v-bind:class="(appConfig.darkMode == 'on') ? 'connection-status-button-dark-mode' : 'connection-status-button-light-mode'" @click="connectDisconnectFromServer(), provideHapticFeedback()"></div>
97+
</div>
98+
<div class="server-name-text">{{ appConfig.serverName }}</div>
99+
</div>
100+
</div>
101+
102+
<div class="configuration-options-window">
103+
<div class="configuration-buttons-window">
104+
<button class="configuration-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="toggleConnectionType(), provideHapticFeedback()">Connection</button>
105+
<button class="configuration-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="toggleScreenshotStreamType(), provideHapticFeedback()">Screen View</button>
106+
<button class="configuration-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="toggleHapticsVibrations(), provideHapticFeedback()">Haptics</button>
107+
<button class="configuration-buttons" v-bind:class="(appConfig.darkMode == 'on') ? 'button-dark-mode' : 'button-light-mode'" @click="toggleDarkOrLightMode(), provideHapticFeedback()">Dark Mode</button>
108+
</div>
109+
110+
<div class="configuration-states-window">
111+
<div class="configuration-states">
112+
<div class="options-text" v-bind:class="(appConfig.connectionType == 'websocket') ? 'selected-option' : 'un-selected-option'">websocket</div>
113+
<div class="options-text" v-bind:class="(appConfig.connectionType == 'http') ? 'selected-option' : 'un-selected-option'">http</div>
114+
</div>
115+
116+
<div class="configuration-states">
117+
<div class="options-text" v-bind:class="(appConfig.screenshotStreamType == 'live') ? 'selected-option' : 'un-selected-option'">live</div>
118+
<div class="options-text" v-bind:class="(appConfig.screenshotStreamType == 'reactive') ? 'selected-option' : 'un-selected-option'">reactive</div>
119+
</div>
120+
121+
<div class="configuration-states">
122+
<div class="options-text" v-bind:class="(appConfig.hapticsVibrations == 'on') ? 'selected-option' : 'un-selected-option'">on</div>
123+
<div class="options-text" v-bind:class="(appConfig.hapticsVibrations == 'off') ? 'selected-option' : 'un-selected-option'">off</div>
124+
</div>
125+
126+
<div class="configuration-states">
127+
<div class="options-text" v-bind:class="(appConfig.darkMode == 'on') ? 'selected-option' : 'un-selected-option'">on</div>
128+
<div class="options-text" v-bind:class="(appConfig.darkMode == 'off') ? 'selected-option' : 'un-selected-option'">off</div>
129+
</div>
130+
</div>
131+
</div>
132+
133+
<button class="action-buttons" @click="backToMainScreen(), provideHapticFeedback()">Back</button>
134+
135+
<!--<input type="checkbox" class="toggle" id="optionToggle">-->
136+
<!--<button class="toggle" id="optionToggle"></button>-->
137+
</div>
138+
</div>
139+
140+
<script src="index.js"></script>
141+
</body>
142+
</html>
143+

0 commit comments

Comments
 (0)