fix gateway server listener memory leak and add token importing to the frontend
This commit is contained in:
parent
b95af521a3
commit
52df7bb4af
5 changed files with 112 additions and 64 deletions
|
@ -26,7 +26,7 @@ class GatewayServer {
|
|||
this.onMessage(ws, data, isBinary);
|
||||
});
|
||||
ws.on("close", (code, reason) => {
|
||||
this.onDisconnect(code, reason.toString());
|
||||
this.onDisconnect(ws, code, reason.toString());
|
||||
});
|
||||
ws.on("pong", () => {
|
||||
this.onPong(ws);
|
||||
|
@ -151,7 +151,7 @@ class GatewayServer {
|
|||
type: "ADD_HANDLER",
|
||||
handler: handle,
|
||||
guildId
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
|
@ -182,8 +182,8 @@ class GatewayServer {
|
|||
}
|
||||
}
|
||||
|
||||
onDisconnect(ws) {
|
||||
if (ws.state && ws.state.handlers && ws.state.handlers.length > 0) {
|
||||
onDisconnect(ws, code, reason) {
|
||||
if (ws.state && ws.state.handlers) {
|
||||
for (const [guildId, handler] of ws.state.handlers.entries()) {
|
||||
const guild = guildMap.get(guildId);
|
||||
if (guild) {
|
||||
|
|
|
@ -2,4 +2,4 @@ export const mainHttpListenPort = 4050;
|
|||
export const watchedGuildIds = ["822089558886842418"];
|
||||
export const jwtSecret = process.env.JWT_SECRET;
|
||||
export const discordToken = process.env.DISCORD_TOKEN;
|
||||
export const dangerousAdminMode = false;
|
||||
export const dangerousAdminMode = true;
|
||||
|
|
|
@ -134,7 +134,7 @@ button:focus {
|
|||
}
|
||||
|
||||
.main-panel-header {
|
||||
font-size: 1.1em;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import { apiClient } from "../api/common";
|
||||
import GatewayClient from "../api/GatewayClient";
|
||||
import { gatewayBase, getRuntimeConfigField } from "../config";
|
||||
import { gatewayBase, getRuntimeConfigField, setRuntimeConfigField } from "../config";
|
||||
import { supportsWebsockets } from "../util/browser";
|
||||
import ChatView from "./ChatView.svelte";
|
||||
import FuzzyView from "./FuzzyView.svelte";
|
||||
|
@ -12,7 +12,76 @@
|
|||
let selectedChannel = null;
|
||||
let guilds = [];
|
||||
let user = null;
|
||||
let view = { type: "CHAT" };
|
||||
let view = { type: "MESSAGE_DISPLAY", header: "Loading...", content: "" };
|
||||
|
||||
let hash = location.hash;
|
||||
let routeInfo = [];
|
||||
if (hash === "")
|
||||
hash = "#";
|
||||
|
||||
hash = hash.substring(1, hash.length);
|
||||
if (hash !== "") {
|
||||
routeInfo = hash.split("||");
|
||||
}
|
||||
|
||||
function doChatLogin() {
|
||||
apiClient.getRequest("/users/@self", false)
|
||||
.then((res) => {
|
||||
let userErrorMessage = "";
|
||||
if (res.error) {
|
||||
userErrorMessage = "Something went wrong while trying to connect you.";
|
||||
if (res.message === "ERROR_UNAUTHORIZED" || res.message === "ERROR_FORBIDDEN") {
|
||||
userErrorMessage = "You're not logged in or your session is invalid. Your bridge administrator should have given you a token to log in with.";
|
||||
}
|
||||
view = { type: "MESSAGE_DISPLAY", header: "Error", content: userErrorMessage };
|
||||
return;
|
||||
}
|
||||
|
||||
user = res.user;
|
||||
|
||||
apiClient.getRequest("/users/@self/guilds")
|
||||
.then((res) => {
|
||||
let userErrorMessage = "";
|
||||
if (res.error) {
|
||||
userErrorMessage = "Something went wrong while trying to fetch guild info.";
|
||||
if (res.message === "ERROR_UNAUTHORIZED" || res.message === "ERROR_FORBIDDEN") {
|
||||
userErrorMessage = "You're not logged in or your session is invalid.";
|
||||
}
|
||||
view = { type: "MESSAGE_DISPLAY", header: "Error", content: userErrorMessage };
|
||||
return;
|
||||
}
|
||||
|
||||
guilds = res.guilds
|
||||
.map(e => {
|
||||
// we only want text channels
|
||||
e.channels = e.channels.filter(c => c.type === 0);
|
||||
return e;
|
||||
});
|
||||
|
||||
// by default, we select the first guild and the first channel in that guild
|
||||
if (guilds.length > 0) {
|
||||
selectedGuild = guilds[0];
|
||||
if (guilds[0].channels.length > 0)
|
||||
selectedChannel = guilds[0].channels[0];
|
||||
}
|
||||
|
||||
view = { type: "CHAT" };
|
||||
});
|
||||
|
||||
if (supportsWebsockets() && !getRuntimeConfigField("f_disableWebsockets")) {
|
||||
console.log("App: browser supports WebSocket, using gateway");
|
||||
const gatewayConnection = new GatewayClient(gatewayBase);
|
||||
gatewayConnection.onEvent = handleEvent;
|
||||
gatewayConnection.connect(apiClient.token);
|
||||
} else {
|
||||
console.warn("App: browser does not support WebSocket (or it is disabled), using polling");
|
||||
const { poll } = apiClient.createPollingListener(null, ({ event }) => {
|
||||
handleEvent(event);
|
||||
});
|
||||
poll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleEvent(event) {
|
||||
if (event.eventType === "MESSAGE_CREATE") {
|
||||
|
@ -34,61 +103,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
apiClient.getRequest("/users/@self", false)
|
||||
.then((res) => {
|
||||
let userErrorMessage = "";
|
||||
if (res.error) {
|
||||
userErrorMessage = "Something went wrong while trying to fetch current user info.";
|
||||
if (res.message === "ERROR_UNAUTHORIZED" || res.message === "ERROR_FORBIDDEN") {
|
||||
userErrorMessage = "You're not logged in or your session is invalid.";
|
||||
}
|
||||
view = { type: "MESSAGE_DISPLAY", header: "Error", content: userErrorMessage };
|
||||
return;
|
||||
}
|
||||
|
||||
user = res.user;
|
||||
});
|
||||
|
||||
apiClient.getRequest("/users/@self/guilds")
|
||||
.then((res) => {
|
||||
let userErrorMessage = "";
|
||||
if (res.error) {
|
||||
userErrorMessage = "Something went wrong while trying to fetch guild info.";
|
||||
if (res.message === "ERROR_UNAUTHORIZED" || res.message === "ERROR_FORBIDDEN") {
|
||||
userErrorMessage = "You're not logged in or your session is invalid.";
|
||||
}
|
||||
view = { type: "MESSAGE_DISPLAY", header: "Error", content: userErrorMessage };
|
||||
return;
|
||||
}
|
||||
|
||||
guilds = res.guilds
|
||||
.map(e => {
|
||||
// we only want text channels
|
||||
e.channels = e.channels.filter(c => c.type === 0);
|
||||
return e;
|
||||
});
|
||||
|
||||
// by default, we select the first guild and the first channel in that guild
|
||||
if (guilds.length > 0) {
|
||||
selectedGuild = guilds[0];
|
||||
if (guilds[0].channels.length > 0)
|
||||
selectedChannel = guilds[0].channels[0];
|
||||
}
|
||||
});
|
||||
|
||||
if (supportsWebsockets() && !getRuntimeConfigField("f_disableWebsockets")) {
|
||||
console.log("App: browser supports WebSocket, using gateway");
|
||||
const gatewayConnection = new GatewayClient(gatewayBase);
|
||||
gatewayConnection.onEvent = handleEvent;
|
||||
gatewayConnection.connect(apiClient.token);
|
||||
} else {
|
||||
console.warn("App: browser does not support WebSocket (or it is disabled), using polling");
|
||||
const { poll } = apiClient.createPollingListener(null, ({ event }) => {
|
||||
handleEvent(event);
|
||||
});
|
||||
poll();
|
||||
}
|
||||
|
||||
function onTextEntryMessage(event) {
|
||||
const content = event.detail;
|
||||
if (content.startsWith(":") && content.length > 1) {
|
||||
|
@ -157,6 +171,33 @@
|
|||
selectedChannel = selectedGuild.channels.find(e => e.id === id);
|
||||
view = { type: "CHAT" };
|
||||
}
|
||||
|
||||
function fuzzyConfirmToken({ detail: yn }) {
|
||||
if (yn === "Yes") {
|
||||
location.hash = "";
|
||||
setRuntimeConfigField("token", view.token);
|
||||
apiClient.token = view.token;
|
||||
doChatLogin();
|
||||
} else if (yn === "No") {
|
||||
view = { type: "MESSAGE_DISPLAY", header: "Got it!", content: "We won't import this token right now." };
|
||||
} else {
|
||||
view = { type: "MESSAGE_DISPLAY", header: "Oops!", content: "We can't import this token right now." };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (routeInfo.length >= 2) {
|
||||
switch (routeInfo[0]) {
|
||||
case "token_handoff": {
|
||||
view = { type: "REDEEM_TOKEN_CONFIRM_PROMPT", token: routeInfo[1] };
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no special route, continue normal execution
|
||||
doChatLogin();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -187,5 +228,7 @@
|
|||
<FuzzyView on:selected={fuzzySelectedChannel} elements={selectedGuild ? selectedGuild.channels : []} title={`Select a channel in ${selectedGuild ? selectedGuild.name : "[unknown guild]"}`} />
|
||||
{:else if view.type === "MESSAGE_DISPLAY"}
|
||||
<MessageDisplay header={ view.header } content={ view.content } ></MessageDisplay>
|
||||
{:else if view.type === "REDEEM_TOKEN_CONFIRM_PROMPT"}
|
||||
<FuzzyView on:selected={fuzzyConfirmToken} elements={[{name: "Yes", id: "Yes"}, {name: "No", id: "No"}]} title="Would you like to import this token? It might've been created for you by your bridge administrator, or a bridge application. Only import tokens you own and trust." />
|
||||
{/if}
|
||||
</main>
|
||||
|
|
|
@ -39,10 +39,15 @@
|
|||
.center-text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heading {
|
||||
display: inline-block;
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="card full-card option-card">
|
||||
<span class="main-panel-header">{ title }</span>
|
||||
<span class="main-panel-header heading">{ title }</span>
|
||||
{#each displayedElements as element, index}
|
||||
{#if index === 0}
|
||||
<button class="button button-selected option-button" on:click={elementClicked(element.id)}>{ element.name }</button>
|
||||
|
|
Loading…
Reference in a new issue