Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Commit

Permalink
Minimal working Web UI!
Browse files Browse the repository at this point in the history
  • Loading branch information
PoneyClairDeLune committed Mar 27, 2023
1 parent 8592d3f commit 5f32a48
Show file tree
Hide file tree
Showing 14 changed files with 151 additions and 18 deletions.
4 changes: 2 additions & 2 deletions CREDITS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
### JavaScript
* Lumière Élevé (core code, Deno interface, Node.js interface)
* Lumière Élevé (core code, Deno interface, Node.js interface, Web UI)

### OS support
* Lumière Élevé (Linux, Android, Windows, macOS, iOS)
* Azure Star/Fauli1221 (Android tester, iOS tester, iSH `env` dump, iSH `uname` dump)
* JayB (macOS `env` dump)
* Starshine (Windows tester, iOS tester)
* Starshine (Windows tester, iOS tester)
2 changes: 2 additions & 0 deletions conf/service/pointer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
"https://ponyplace.z19.web.core.windows.net/mask.png",
"https://media.githubusercontent.com/media/r-ainbowroad/2023-minimap/main/mlp/mask.png"
],
"regions": [
],
"offX": 0,
"offY": 0
}
5 changes: 5 additions & 0 deletions dist/web.js.txt

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions libs/alpinejs/alpine.js

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions libs/lightfelt/main/cssClass.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"use strict";

DOMTokenList.prototype.on = function (classNme) {
!this.contains(classNme) && this.toggle(classNme);
};
DOMTokenList.prototype.off = function (classNme) {
this.contains(classNme) && this.toggle(classNme);
};
3 changes: 1 addition & 2 deletions libs/picocss/pico.css

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions sh/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ mkdir -p proxy
rm -rv dist/*.js
rm -rv dist/*.mjs
rm -rv dist/*.map
# Build some files ahead of the time
shx live web --minify > /dev/null
mv proxy/web.js dist/web.js.txt
# Using esbuild to build all JS files
#esbuild --bundle src/index.js --outfile=dist/index.js --minify --sourcemap
#esbuild --bundle src/index.js --target=es6 --outfile=dist/index.es6.js --minify --sourcemap
Expand All @@ -29,8 +32,4 @@ ls -1 src | while IFS= read -r dir ; do
cat proxy/${dir}.${ext} >> dist/${dir}.${ext}
fi
done
# Node specific
#mkdir -p proxy/node
#mv dist/node.js proxy/node/index.js
#rm proxy/node.js
exit
2 changes: 1 addition & 1 deletion src/core/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const dim2Prop = [0, 1];

let BuildInfo = {
name: "Painted Palette",
ver: "0.0.6"
ver: "0.0.7"
};

let dim3Dist = function (a, b) {
Expand Down
29 changes: 24 additions & 5 deletions src/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
"use strict";

import {BuildInfo, stringReflector} from "./common.js";
import {IPInfo} from "../core/ipinfo.js";
import {FetchContext} from "./fetchContext.js";
import {RedditAuth} from "./redditAuth.js";
import {Monalisa} from "./monalisa.js";
import webUiBody from "../web/index.htm";
import webUiCss from "../web/index.css";
import picoCss from "../../libs/picocss/pico.css";
import webUiJs from "../web/web.txt";
import webUiJs from "../../dist/web.js.txt";

const svc = {
cnc: "",
Expand Down Expand Up @@ -50,7 +51,7 @@ let waitForProxy = async function () {
let proxyOn = WingBlade.getEnv("HTTPS_PROXY");
if (proxyOn) {
console.info(`Waiting for the proxy client on ${proxyOn} ...`);
await WingBlade.sleep(4000);
await WingBlade.sleep(1000);
};
};

Expand Down Expand Up @@ -158,8 +159,10 @@ let main = async function (args) {
};
case "batch": {
await waitForProxy();
let confFile = acct || "config.json";
console.info(`Reading configuration data from "${confFile}".`);
let confFile = parseInt(acct) || 14514;
console.info(`Reading configuration data from "${confFile}.json".`);
let ipInfo = new IPInfo();
ipInfo.start();
WingBlade.serve(async function (request) {
let badRequest = new Response("Bad Request", {
status: 400
Expand Down Expand Up @@ -204,6 +207,22 @@ let main = async function (args) {
});
break;
};
case "/info": {
return new Response(JSON.stringify({
ip: {
ip: ipInfo.ip,
cc: ipInfo.cc,
asn: ipInfo.asn,
as: ipInfo.as
},
proxy: WingBlade.getEnv("HTTPS_PROXY") ? (WingBlade.getEnv("PROXY_PORT") ? "Standalone" : "System") : "No Proxy"
}), {
"headers": {
"Content-Type": "application/json"
}
});
break;
};
default: {
return notFound;
};
Expand All @@ -225,7 +244,7 @@ let main = async function (args) {
};
};
}, {
port: 14514,
port: acct || 14514,
onListen: ({port}) => {
console.info(`Now running in batch mode. To control and/or retrieve info from CLI, use the "ctl" subcommand.`);
console.info(`Web UI and REST API available on http://127.0.0.1:${port}/`);
Expand Down
73 changes: 73 additions & 0 deletions src/core/ipinfo.js
Original file line number Diff line number Diff line change
@@ -1 +1,74 @@
"use strict";

import {FetchContext} from "./fetchContext.js";

const remotes = ["https://ifconfig.me/ip", "https://ipecho.net/plain"];

let IPInfo = class {
#fc = new FetchContext();
#monitorThread = 0;
#infoIp = "127.0.0.1";
ip = "127.0.0.1";
cc = "UN";
asn = 0;
as = "Invalid ASN";
start() {
let upThis = this;
this.#monitorThread = setInterval(() => {
upThis.grab();
}, 20000);
upThis.grab();
};
stop() {
clearInterval(this.#monitorThread);
this.#monitorThread = 0;
};
async grab() {
// Fetch
let ipAddress = "127.0.0.1";
try {
ipAddress = (await (await this.#fc.fetch(remotes[WingBlade.randomInt(remotes.length)])).text()).replaceAll("\n", "").trim();
} catch (err) {
console.info(`IP address fetch failed. ${err}`);
};
if (this.#infoIp != ipAddress && ipAddress != "127.0.0.1" && ipAddress != this.ip) {
console.info(`IP address updated to: ${ipAddress}`);
this.ip = ipAddress;
let ipInfo;
try {
let ipsb = await this.#fc.fetch(`https://api.ip.sb/geoip/${ipAddress}`);
if (ipsb.status == 200) {
let ipInfo = await ipsb.json();
this.asn = ipInfo.asn || 0;
this.as = ipInfo.isp || ipInfo.asn_organization || "Invalid ASN";
this.cc = ipInfo.country_code || ipInfo.region_code || "UN";
} else {
// Fetch information from BGPView
let ipInfo = (await(await this.#fc.fetch(`https://api.bgpview.io/ip/${ipAddress}`)).json()).data;
// Extract AS information
ipInfo.prefixes.sort((a, b) => {
return b.cidr - a.cidr;
});
this.asn = ipInfo.prefixes[0]?.asn.asn || 0;
this.as = ipInfo.prefixes[0]?.asn.description || "Invalid ASN";
// Extract country code
if (ipInfo.maxmind.country_code) {
this.cc = ipInfo.maxmind.country_code;
} else {
this.cc = ipInfo.prefixes[0].country_code;
};
this.#infoIp = ipAddress;
};
//console.info(this);
} catch (err) {};
} else {
//console.info(`IP address still on: ${ipAddress}`);
};
};
constructor() {
};
};

export {
IPInfo
};
2 changes: 1 addition & 1 deletion src/web/index.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/web/index.htm
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><title>Painted Palette Web UI</title><link rel="stylesheet" href="./pico.css"><link rel="stylesheet" href="./index.css"><script src="./index.js"></script></head><body><div class="container"><nav><ul><li><b>Painted Palette Dashboard</b></li></ul><ul><li><a href="#a" role="button">Accounts</a></li><li><a href="#s">Info</a></li><li><a href="#c">About</a></li></ul></nav><div id="tab-containers"><div id="tab-a" class="tab-on container-fluid"><div class="grid"><button id="btn-gon" data-tooltip="Enable all managed accounts.">All On</button><button id="btn-goff" data-tooltip="Disable all managed accounts.">All Off</button><button id="btn-full" data-tooltip="Set power to 1 (bots run at full force).">P=1</button><button id="btn-half" data-tooltip="Set power to 0.5 (bots run at half power).">P=0.5</button><button id="btn-empty" data-tooltip="Set power to 0 (bots rest).">P=0</button><button id="btn-grem" data-tooltip="Reset power value to be provided by CnC.">CnC Reset</button><button id="btn-fr" data-tooltip="Force random redistribution of focal points.">Refocus</button></div><div class="grid"><input id="in-acct" placeholder="Account"></input><input id="in-pass" type="password" placeholder="Password"></input><input id="in-otp" placeholder="2FA OTP (Optional)"></input><button id="btn-add" data-tooltip="Add the account for management and attempt login.">Login</button></div><table><thead><tr><th>Account</th><th>Next in</th><th>Active</th><th>Placed</th><th>Focus</th><th>Actions</th></tr></thead><tbody><tr><td>Example</td><td>Standby</td><td>Yes</td><td><span class="b-palette" style="background:#fff"></span> 12</td><td>114, 514</td><td><a href="javascript:void()">Toggle</a> <a href="javascript:void()">Remove</a></td></tr><tr><td>Dummy</td><td>3s</td><td>Yes</td><td><span class="b-palette" style="background:#fe0"></span> 6</td><td>1919, 810</td><td><a href="javascript:void()">Toggle</a> <a href="javascript:void()">Remove</a></td></tr></tbody></table></div></div></div></body></html>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><title>Painted Palette Web UI</title><link rel="stylesheet" href="./pico.css"><link rel="stylesheet" href="./index.css"><script defer src="./index.js"></script></head><body><div class="container" x-data="{tab:0,showIp:false}"><nav><ul><li><b>Painted Palette Dashboard</b></li></ul><ul><li><a href="#" @mouseup="tab=0">Accounts</a></li><li><a href="#" @mouseup="tab=1">Info</a></li><li><a href="#" @mouseup="tab=2">About</a></li></ul></nav><div id="tab-containers"><div id="tab-a" class="tab-on container-fluid" x-show="tab==0"><div class="grid"><button id="btn-gon" data-tooltip="Enable all managed accounts.">All On</button><button id="btn-goff" data-tooltip="Disable all managed accounts.">All Off</button><button id="btn-full" data-tooltip="Set power to 1 (bots run at full force).">P=1</button><button id="btn-half" data-tooltip="Set power to 0.5 (bots run at half power).">P=0.5</button><button id="btn-empty" data-tooltip="Set power to 0 (bots rest).">P=0</button><button id="btn-grem" data-tooltip="Reset power value to be provided by CnC.">CnC Reset</button><button id="btn-fr" data-tooltip="Force random redistribution of focal points.">Refocus</button></div><div class="grid"><input id="in-acct" placeholder="Account"></input><input id="in-pass" type="password" placeholder="Password"></input><input id="in-otp" placeholder="2FA OTP (Optional)"></input><button id="btn-add" data-tooltip="Add the account for management and attempt login.">Login</button></div><table><thead><tr><th>Account</th><th>Next in</th><th>Active</th><th>Placed</th><th>Focus</th><th>Actions</th></tr></thead><tbody><tr><td>Example</td><td>Standby</td><td>Yes</td><td><span class="b-palette" style="background:#fff"></span> 12</td><td>114, 514</td><td><a href="javascript:void()">Toggle</a> <a href="javascript:void()">Remove</a></td></tr><tr><td>Dummy</td><td>3s</td><td>Yes</td><td><span class="b-palette" style="background:#fe0"></span> 6</td><td>1919, 810</td><td><a href="javascript:void()">Toggle</a> <a href="javascript:void()">Remove</a></td></tr></tbody></table></div><div x-show="tab==1"><div><big><b>IP info</b></big> <a href="#" @mouseup="showIp=!showIp" x-text="['Show','Hide'][+showIp]"></a></div><table><thead><tr><th>Proxy</th><th>IP</th><th>Country</th><th>ASN</th><th>AS Name</th></tr></thead><tbody><tr><td x-text="$store.info?.proxy||'N/A'"></td><td x-text="showIp?($store.info?.ip||'0.0.0.0'):'Hidden'">IP</td><td x-text="showIp?($store.info?.cc||'XX'):'Hidden'">Country</td><td x-text="showIp?($store.info?.asn||0):'Hidden'">ASN</td><td x-text="showIp?($store.info?.as||'Unknown AS'):'Hidden'">AS Name</td></tr></tbody></table><div><big><b>Managed Stats</b></big></div><table><tbody><tr><th>Accounts</th><td>0</td></tr><tr><th>Placed Pixels</th><td>0</td><tr><th>Uptime</th><td>0d 00:00:00</td></tr></tr></tbody></table></div><div x-show="tab==2"><h4>About</h4><table><tbody><tr><th colspan="2" class="text-center" x-text="$store.buildInfo?.name||'appName'"></th></tr><tr><th>Version</th><td x-text="$store.buildInfo?.ver||'appVer'"></td></tr><tr><th>Developed by</th><td>Lumière Élevé</td></tr><tr><th>Tested by</th><td>Lumière Élevé<br/>Fauli1221<br/>Starshine</td></tr><tr><th>Produced by</th><td>Lightingale Community</td></tr></tbody></table></div></div></div></body></html>
25 changes: 25 additions & 0 deletions src/web/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Only place minimized files here
"use strict";

// Import common values
import {BuildInfo} from "../core/common.js";

// Initialize Alpine
import {} from "../../libs/alpinejs/alpine.js";

let infoThread = 0;

// Some serious work
document.addEventListener("alpine:init", () => {
Alpine.store("buildInfo", BuildInfo);
infoThread = setInterval(async () => {
let data = await (await fetch("/info")).json();
Alpine.store("info", {
ip: data.ip.ip || "127.0.0.1",
cc: data.ip.cc || "UN",
asn: data.ip.asn || 0,
as: data.ip.as || "Invalid ASN",
proxy: data.proxy
});
}, 5000);
});
2 changes: 0 additions & 2 deletions src/web/web.txt

This file was deleted.

0 comments on commit 5f32a48

Please sign in to comment.