diff options
Diffstat (limited to 'static')
-rw-r--r-- | static/src/assets/api.js | 52 | ||||
-rw-r--r-- | static/src/chat.md | 126 |
2 files changed, 175 insertions, 3 deletions
diff --git a/static/src/assets/api.js b/static/src/assets/api.js index 7ce2e89..4447bb1 100644 --- a/static/src/assets/api.js +++ b/static/src/assets/api.js @@ -1,5 +1,7 @@ import * as utils from "/assets/utils.js"; +const csrfTokenCookie = "csrf_token"; + const doFetch = async (req) => { let res, jsonRes; try { @@ -53,13 +55,13 @@ const call = async (route, opts = {}) => { requiresPow = false, } = opts; - if (!utils.cookies["csrf_token"]) - throw "csrf_token cookie not set, can't make api call"; + if (!utils.cookies[csrfTokenCookie]) + throw `${csrfTokenCookie} cookie not set, can't make api call`; const reqOpts = { method, headers: { - "X-CSRF-Token": utils.cookies["csrf_token"], + "X-CSRF-Token": utils.cookies[csrfTokenCookie], }, }; @@ -80,6 +82,50 @@ const call = async (route, opts = {}) => { return doFetch(req); } +const ws = async (route, opts = {}) => { + const { + requiresPow = false, + } = opts; + + const docURL = new URL(document.URL); + const protocol = docURL.protocol == "http:" ? "ws:" : "wss:"; + + const params = new URLSearchParams(); + const csrfToken = utils.cookies[csrfTokenCookie]; + + if (!csrfToken) + throw `${csrfTokenCookie} cookie not set, can't make api call`; + + params.set("csrfToken", csrfToken); + + if (requiresPow) { + const {seed, solution} = await solvePow(); + params.set("powSeed", seed); + params.set("powSolution", solution); + } + + const rawConn = new WebSocket(`${protocol}//${docURL.host}${route}?${params.toString()}`); + + const conn = { + next: () => new Promise((resolve, reject) => { + rawConn.onmessage = (m) => { + const mj = JSON.parse(m.data); + resolve(mj); + }; + rawConn.onerror = reject; + rawConn.onclose = reject; + }), + + close: rawConn.close, + }; + + return new Promise((resolve, reject) => { + rawConn.onopen = () => resolve(conn); + rawConn.onerror = reject; + }); +} + export { call, + ws } diff --git a/static/src/chat.md b/static/src/chat.md new file mode 100644 index 0000000..c7471ef --- /dev/null +++ b/static/src/chat.md @@ -0,0 +1,126 @@ +--- +layout: page +--- + +<script async type="module" src="/assets/api.js"></script> + +<style> + #messages { + max-height: 65vh; + overflow: auto; + } + + #messages .message { + border: 1px solid #AAA; + border-radius: 10px; + margin-bottom: 1rem; + padding: 2rem; + overflow: auto; + } + + #messages .message .title { + font-weight: bold; + font-size: 120%; + } + + #messages .message .secondaryTitle { + font-family: monospace; + color: #CCC; + } + + #messages .message p { + font-family: monospace; + margin: 1rem 0 0 0; + } + +</style> + +<div id="messages"></div> + +<span id="fail" style="color: red;"></span> + +<script> + +const messagesEl = document.getElementById("messages"); + +function renderMessages(msgs) { + + msgs = [...msgs].reverse(); + + messagesEl.innerHTML = ''; + + msgs.forEach((msg) => { + console.log(msg); + const el = document.createElement("div"); + el.className = "row message" + + const elWithTextContents = (tag, body) => { + const el = document.createElement(tag); + el.appendChild(document.createTextNode(body)); + return el; + }; + + const titleEl = document.createElement("div"); + titleEl.className = "title"; + el.appendChild(titleEl); + + const userNameEl = elWithTextContents("span", msg.userID.name); + titleEl.appendChild(userNameEl); + + const secondaryTitleEl = document.createElement("div"); + secondaryTitleEl.className = "secondaryTitle"; + el.appendChild(secondaryTitleEl); + + const dt = new Date(msg.createdAt*1000); + const dtStr + = `${dt.getFullYear()}-${dt.getMonth()+1}-${dt.getDate()}` + + ` ${dt.getHours()}:${dt.getMinutes()}:${dt.getSeconds()}`; + + const userIDEl = elWithTextContents("span", `userID:${msg.userID.id} @ ${dtStr}`); + secondaryTitleEl.appendChild(userIDEl); + + const bodyEl = document.createElement("p"); + + const bodyParts = msg.body.split("\n"); + for (const i in bodyParts) { + if (i > 0) bodyEl.appendChild(document.createElement("br")); + bodyEl.appendChild(document.createTextNode(bodyParts[i])); + } + + el.appendChild(bodyEl); + + messagesEl.appendChild(el); + }); +} + + +(async () => { + + const failEl = document.getElementById("fail"); + + setErr = (msg) => failEl.innerHTML = `${msg} (please refresh the page to retry)`; + + const api = await import("/assets/api.js"); + + try { + + const history = await api.call("/api/chat/global/history"); + renderMessages(history.messages); + + } catch (e) { + e = `Failed to fetch message history: ${e}` + setErr(e); + console.error(e); + return; + } + + //const ws = await api.ws("/api/chat/global/listen"); + + //while (true) { + // const msg = await ws.next(); + // console.log("got msg", msg); + //} + +})() + +</script> |