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);
|
this.onMessage(ws, data, isBinary);
|
||||||
});
|
});
|
||||||
ws.on("close", (code, reason) => {
|
ws.on("close", (code, reason) => {
|
||||||
this.onDisconnect(code, reason.toString());
|
this.onDisconnect(ws, code, reason.toString());
|
||||||
});
|
});
|
||||||
ws.on("pong", () => {
|
ws.on("pong", () => {
|
||||||
this.onPong(ws);
|
this.onPong(ws);
|
||||||
|
@ -151,7 +151,7 @@ class GatewayServer {
|
||||||
type: "ADD_HANDLER",
|
type: "ADD_HANDLER",
|
||||||
handler: handle,
|
handler: handle,
|
||||||
guildId
|
guildId
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
|
@ -182,8 +182,8 @@ class GatewayServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDisconnect(ws) {
|
onDisconnect(ws, code, reason) {
|
||||||
if (ws.state && ws.state.handlers && ws.state.handlers.length > 0) {
|
if (ws.state && ws.state.handlers) {
|
||||||
for (const [guildId, handler] of ws.state.handlers.entries()) {
|
for (const [guildId, handler] of ws.state.handlers.entries()) {
|
||||||
const guild = guildMap.get(guildId);
|
const guild = guildMap.get(guildId);
|
||||||
if (guild) {
|
if (guild) {
|
||||||
|
|
|
@ -2,4 +2,4 @@ export const mainHttpListenPort = 4050;
|
||||||
export const watchedGuildIds = ["822089558886842418"];
|
export const watchedGuildIds = ["822089558886842418"];
|
||||||
export const jwtSecret = process.env.JWT_SECRET;
|
export const jwtSecret = process.env.JWT_SECRET;
|
||||||
export const discordToken = process.env.DISCORD_TOKEN;
|
export const discordToken = process.env.DISCORD_TOKEN;
|
||||||
export const dangerousAdminMode = false;
|
export const dangerousAdminMode = true;
|
||||||
|
|
|
@ -134,7 +134,7 @@ button:focus {
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-panel-header {
|
.main-panel-header {
|
||||||
font-size: 1.1em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error-text {
|
.error-text {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { apiClient } from "../api/common";
|
import { apiClient } from "../api/common";
|
||||||
import GatewayClient from "../api/GatewayClient";
|
import GatewayClient from "../api/GatewayClient";
|
||||||
import { gatewayBase, getRuntimeConfigField } from "../config";
|
import { gatewayBase, getRuntimeConfigField, setRuntimeConfigField } from "../config";
|
||||||
import { supportsWebsockets } from "../util/browser";
|
import { supportsWebsockets } from "../util/browser";
|
||||||
import ChatView from "./ChatView.svelte";
|
import ChatView from "./ChatView.svelte";
|
||||||
import FuzzyView from "./FuzzyView.svelte";
|
import FuzzyView from "./FuzzyView.svelte";
|
||||||
|
@ -12,7 +12,76 @@
|
||||||
let selectedChannel = null;
|
let selectedChannel = null;
|
||||||
let guilds = [];
|
let guilds = [];
|
||||||
let user = null;
|
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) {
|
function handleEvent(event) {
|
||||||
if (event.eventType === "MESSAGE_CREATE") {
|
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) {
|
function onTextEntryMessage(event) {
|
||||||
const content = event.detail;
|
const content = event.detail;
|
||||||
if (content.startsWith(":") && content.length > 1) {
|
if (content.startsWith(":") && content.length > 1) {
|
||||||
|
@ -157,6 +171,33 @@
|
||||||
selectedChannel = selectedGuild.channels.find(e => e.id === id);
|
selectedChannel = selectedGuild.channels.find(e => e.id === id);
|
||||||
view = { type: "CHAT" };
|
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>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -187,5 +228,7 @@
|
||||||
<FuzzyView on:selected={fuzzySelectedChannel} elements={selectedGuild ? selectedGuild.channels : []} title={`Select a channel in ${selectedGuild ? selectedGuild.name : "[unknown guild]"}`} />
|
<FuzzyView on:selected={fuzzySelectedChannel} elements={selectedGuild ? selectedGuild.channels : []} title={`Select a channel in ${selectedGuild ? selectedGuild.name : "[unknown guild]"}`} />
|
||||||
{:else if view.type === "MESSAGE_DISPLAY"}
|
{:else if view.type === "MESSAGE_DISPLAY"}
|
||||||
<MessageDisplay header={ view.header } content={ view.content } ></MessageDisplay>
|
<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}
|
{/if}
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -39,10 +39,15 @@
|
||||||
.center-text {
|
.center-text {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
display: inline-block;
|
||||||
|
padding-bottom: 14px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="card full-card option-card">
|
<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}
|
{#each displayedElements as element, index}
|
||||||
{#if index === 0}
|
{#if index === 0}
|
||||||
<button class="button button-selected option-button" on:click={elementClicked(element.id)}>{ element.name }</button>
|
<button class="button button-selected option-button" on:click={elementClicked(element.id)}>{ element.name }</button>
|
||||||
|
|
Loading…
Reference in a new issue