add.. something.....
This commit is contained in:
parent
fea27f9fa9
commit
4fbdace446
5 changed files with 360 additions and 0 deletions
105
out/_/jd3ymgfg3gk6vrlaxhbn/GatewayClient.js
Normal file
105
out/_/jd3ymgfg3gk6vrlaxhbn/GatewayClient.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
window.modules.register("GatewayClient", () => {
|
||||
const messageSchema = { t: "number", d: "object" };
|
||||
const messageTypes = {
|
||||
HELLO: 0,
|
||||
YOO: 1,
|
||||
READY: 2,
|
||||
EVENT: 3
|
||||
};
|
||||
|
||||
class GatewayClient {
|
||||
constructor(gatewayPath) {
|
||||
this.gatewayPath = gatewayPath;
|
||||
this.ws = null;
|
||||
this.token = null;
|
||||
this.user = null;
|
||||
this.onEvent = (e) => {};
|
||||
this.onConnected = () => {};
|
||||
this.onDisconnected = () => {};
|
||||
}
|
||||
|
||||
connect(token) {
|
||||
if (!token)
|
||||
token = this.token;
|
||||
|
||||
console.log("gateway: connecting");
|
||||
|
||||
this.ws = new WebSocket(this.gatewayPath);
|
||||
|
||||
this.ws.addEventListener("message", ({ data }) => {
|
||||
if (typeof data !== "string") {
|
||||
console.warn("gateway: got non-string data from server, ignoring...");
|
||||
return;
|
||||
}
|
||||
|
||||
let message;
|
||||
try {
|
||||
message = JSON.parse(data);
|
||||
} catch(e) {
|
||||
console.warn("gateway: got invalid JSON from server (failed to parse), ignoring...");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._checkMessageSchema(message)) {
|
||||
console.warn("gateway: got invalid JSON from server (does not match schema), ignoring...");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.t) {
|
||||
case messageTypes.HELLO: {
|
||||
console.log("gateway: HELLO");
|
||||
this.ws.send(JSON.stringify({
|
||||
t: messageTypes.YOO,
|
||||
d: {
|
||||
token
|
||||
}
|
||||
}));
|
||||
break;
|
||||
}
|
||||
case messageTypes.READY: {
|
||||
console.log("gateway: READY");
|
||||
this.user = message.d.user;
|
||||
this.onConnected();
|
||||
break;
|
||||
}
|
||||
case messageTypes.EVENT: {
|
||||
this.onEvent(message.d);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
console.warn("gateway: got invalid JSON from server (invalid type), ignoring...");
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
this.ws.addEventListener("open", () => {
|
||||
console.log("gateway: open");
|
||||
});
|
||||
this.ws.addEventListener("close", ({ code }) => {
|
||||
console.log("gateway: closed");
|
||||
this.onDisconnected(code);
|
||||
if (code === 4001) {
|
||||
console.log(`gateway: disconnect code is ${code} (bad auth), will not attempt reconnect`);
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
console.log("gateway: reconnecting");
|
||||
this.connect(token);
|
||||
}, 4000);
|
||||
});
|
||||
}
|
||||
|
||||
_checkMessageSchema(message) {
|
||||
for (const [key, value] of Object.entries(message)) {
|
||||
if (!messageSchema[key])
|
||||
return false;
|
||||
|
||||
if (typeof value !== messageSchema[key])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return GatewayClient;
|
||||
});
|
21
out/_/jd3ymgfg3gk6vrlaxhbn/app.js
Normal file
21
out/_/jd3ymgfg3gk6vrlaxhbn/app.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
window.modules.register("$app", () => {
|
||||
const App = window.modules.require("App");
|
||||
|
||||
if (!window._APP_ENV)
|
||||
throw new Error("$app: could not find window._APP_ENV");
|
||||
if (!App)
|
||||
throw new Error("$app: require('App') returned undefined");
|
||||
|
||||
const initialLoading = document.getElementById("initial-loading");
|
||||
if (initialLoading) {
|
||||
initialLoading.parentElement.removeChild(initialLoading);
|
||||
}
|
||||
|
||||
const appMountElement = document.createElement("div");
|
||||
document.body.appendChild(appMountElement);
|
||||
|
||||
const app = new App(appMountElement);
|
||||
app.mount();
|
||||
|
||||
return app;
|
||||
});
|
185
out/_/jd3ymgfg3gk6vrlaxhbn/components.js
Normal file
185
out/_/jd3ymgfg3gk6vrlaxhbn/components.js
Normal file
|
@ -0,0 +1,185 @@
|
|||
window.modules.register("AuthPromptRoute", () => {
|
||||
class AuthPromptRoute {
|
||||
constructor() {
|
||||
this.element = null;
|
||||
}
|
||||
|
||||
mountOn(target) {
|
||||
if (this.element)
|
||||
return; // Already mounted
|
||||
|
||||
this.element = document.createRange().createContextualFragment(`
|
||||
<div>
|
||||
<input type="password" id="code-input">
|
||||
<button id="continue-button">enter</button>
|
||||
</div>
|
||||
`).children[0];
|
||||
|
||||
this.element.querySelector("#continue-button").addEventListener("click", () => {
|
||||
if (this.onPasswordSubmitted)
|
||||
this.onPasswordSubmitted(this.element.querySelector("#code-input").value);
|
||||
});
|
||||
|
||||
target.appendChild(this.element);
|
||||
}
|
||||
|
||||
unmount() {
|
||||
if (!this.element)
|
||||
return; // Already unmounted
|
||||
this.element.parentElement.removeChild(this.element);
|
||||
this.element = null;
|
||||
}
|
||||
}
|
||||
|
||||
return AuthPromptRoute;
|
||||
});
|
||||
|
||||
window.modules.register("MainChatView", () => {
|
||||
class MainChatView {
|
||||
constructor() {
|
||||
this.element = null;
|
||||
}
|
||||
|
||||
mountOn(target) {
|
||||
if (this.element)
|
||||
return; // Already mounted
|
||||
|
||||
this.element = document.createRange().createContextualFragment(`
|
||||
<div>
|
||||
<div id="messages-container" style="width: 300px; height: 250px; overflow: auto;"></div>
|
||||
<br>
|
||||
<input type="text" id="message-input">
|
||||
<button id="message-submit">send</button>
|
||||
</div>
|
||||
`).children[0];
|
||||
|
||||
const textInput = this.element.querySelector("#message-input");
|
||||
this.element.querySelector("#message-submit").addEventListener("click", () => {
|
||||
const message = textInput.value;
|
||||
if (this.onSendMessage)
|
||||
this.onSendMessage(message);
|
||||
|
||||
textInput.value = "";
|
||||
});
|
||||
|
||||
target.appendChild(this.element);
|
||||
}
|
||||
|
||||
appendMessage(messageObject) {
|
||||
const { author, content } = messageObject;
|
||||
if (!this.element)
|
||||
return;
|
||||
|
||||
const usernameLetters = author.username
|
||||
.split("");
|
||||
let authorUsernameNumber = 150;
|
||||
usernameLetters.forEach(l => {
|
||||
authorUsernameNumber += l.charCodeAt(0);
|
||||
});
|
||||
|
||||
const messageElement = document.createRange().createContextualFragment(`
|
||||
<div>
|
||||
<b>[author could not be loaded] </b>
|
||||
<span>[content could not be loaded]</span>
|
||||
</div>
|
||||
`).children[0];
|
||||
|
||||
messageElement.querySelector("b").innerText = `User ${authorUsernameNumber} `;
|
||||
messageElement.querySelector("span").innerText = content;
|
||||
|
||||
const container = this.element.querySelector("#messages-container");
|
||||
container.appendChild(messageElement);
|
||||
container.scrollTop = container.scrollHeight;
|
||||
}
|
||||
|
||||
unmount() {
|
||||
if (!this.element)
|
||||
return; // Already unmounted
|
||||
this.element.parentElement.removeChild(this.element);
|
||||
this.element = null;
|
||||
}
|
||||
}
|
||||
|
||||
return MainChatView;
|
||||
});
|
||||
|
||||
|
||||
window.modules.register("App", () => {
|
||||
const AuthPromptRoute = window.modules.require("AuthPromptRoute");
|
||||
const MainChatView = window.modules.require("MainChatView");
|
||||
const GatewayClient = window.modules.require("GatewayClient");
|
||||
|
||||
|
||||
class App {
|
||||
constructor(mountElement) {
|
||||
this.mountElement = mountElement;
|
||||
this.currentMountedElement = null;
|
||||
|
||||
this.authPromptRoute = new AuthPromptRoute();
|
||||
this.mainChatView = new MainChatView();
|
||||
this.gatewayClient = new GatewayClient(window._APP_ENV.gatewayBase);
|
||||
}
|
||||
|
||||
_mountElement(element) {
|
||||
if (this.currentMountedElement) {
|
||||
this.currentMountedElement.unmount();
|
||||
}
|
||||
this.currentMountedElement = element;
|
||||
this.currentMountedElement.mountOn(this.mountElement);
|
||||
}
|
||||
|
||||
_unmountAll() {
|
||||
if (this.currentMountedElement) {
|
||||
this.currentMountedElement.unmount();
|
||||
}
|
||||
}
|
||||
|
||||
mount() {
|
||||
let serverId;
|
||||
let channelId;
|
||||
let token;
|
||||
|
||||
this._mountElement(this.authPromptRoute);
|
||||
|
||||
this.gatewayClient.onEvent = (e) => {
|
||||
if (e.eventType === "MESSAGE_CREATE" && e.message && e.message.guild_id === serverId && e.message.channel_id === channelId) {
|
||||
this.mainChatView.appendMessage(e.message);
|
||||
}
|
||||
};
|
||||
this.gatewayClient.onConnected = () => {
|
||||
this._mountElement(this.mainChatView);
|
||||
};
|
||||
this.gatewayClient.onDisconnected = () => {
|
||||
this._mountElement(this.authPromptRoute);
|
||||
};
|
||||
this.authPromptRoute.onPasswordSubmitted = (auth) => {
|
||||
const parts = auth.split(",,");
|
||||
if (parts.length !== 3)
|
||||
return;
|
||||
|
||||
const [userToken, userServerId, userChannelId] = parts;
|
||||
serverId = userServerId;
|
||||
channelId = userChannelId;
|
||||
token = userToken
|
||||
this.gatewayClient.connect(token);
|
||||
};
|
||||
this.mainChatView.onSendMessage = async (message) => {
|
||||
if (typeof message === "string" && message.trim() === "")
|
||||
return;
|
||||
|
||||
await fetch(`${window._APP_ENV.apiBase}/guilds/${serverId}/channels/${channelId}/messages/create`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
content: message
|
||||
}),
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
"authorization": token
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return App;
|
||||
});
|
23
out/_/jd3ymgfg3gk6vrlaxhbn/index.html
Normal file
23
out/_/jd3ymgfg3gk6vrlaxhbn/index.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>.</title>
|
||||
<script>
|
||||
window._APP_ENV = {
|
||||
gatewayBase: "wss://kittycatnetwork.hippoz.xyz/services/thebridge/gateway/",
|
||||
apiBase: "https://kittycatnetwork.hippoz.xyz/services/thebridge/api/v1"
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p id="initial-loading">loading</p>
|
||||
|
||||
<script src="moduleruntime.js"></script>
|
||||
<script src="GatewayClient.js"></script>
|
||||
<script src="components.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
26
out/_/jd3ymgfg3gk6vrlaxhbn/moduleruntime.js
Normal file
26
out/_/jd3ymgfg3gk6vrlaxhbn/moduleruntime.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
const modules = {
|
||||
_cache: {},
|
||||
_registry: {},
|
||||
require(moduleName) {
|
||||
if (this._cache[moduleName]) {
|
||||
return this._cache[moduleName];
|
||||
}
|
||||
|
||||
if (this._registry[moduleName]) {
|
||||
const loaderFunction = this._registry[moduleName];
|
||||
this._cache[moduleName] = loaderFunction(1);
|
||||
return this._cache[moduleName];
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
register(moduleName, loaderFunction) {
|
||||
this._registry[moduleName] = loaderFunction;
|
||||
this._cache[moduleName] = loaderFunction(0);
|
||||
},
|
||||
registerLazy(moduleName, loaderFunction) {
|
||||
this._registry[moduleName] = loaderFunction;
|
||||
}
|
||||
};
|
||||
|
||||
window.modules = modules;
|
Loading…
Reference in a new issue