summaryrefslogtreecommitdiff
path: root/fig-frontend-client/src
diff options
context:
space:
mode:
Diffstat (limited to 'fig-frontend-client/src')
-rw-r--r--fig-frontend-client/src/Audio.js30
-rw-r--r--fig-frontend-client/src/Audio.purs10
-rw-r--r--fig-frontend-client/src/Auth.js45
-rw-r--r--fig-frontend-client/src/Auth.purs29
-rw-r--r--fig-frontend-client/src/Config.js4
-rw-r--r--fig-frontend-client/src/Config.purs6
-rw-r--r--fig-frontend-client/src/Main.purs156
-rw-r--r--fig-frontend-client/src/Model.js108
-rw-r--r--fig-frontend-client/src/Model.purs10
-rw-r--r--fig-frontend-client/src/UI.js2
-rw-r--r--fig-frontend-client/src/UI.purs13
11 files changed, 0 insertions, 413 deletions
diff --git a/fig-frontend-client/src/Audio.js b/fig-frontend-client/src/Audio.js
deleted file mode 100644
index 2a9ae54..0000000
--- a/fig-frontend-client/src/Audio.js
+++ /dev/null
@@ -1,30 +0,0 @@
-let initialized = false;
-let ctx = null;
-let voiceTracks = null;
-
-function initializeCtx() {
- if (!initialized) {
- try {
- initialized = true;
- ctx = new window.AudioContext();
- voiceTracks = [
- document.getElementById("lcolonq-audio-voice-0"),
- document.getElementById("lcolonq-audio-voice-1"),
- document.getElementById("lcolonq-audio-voice-2"),
- document.getElementById("lcolonq-audio-voice-3"),
- document.getElementById("lcolonq-audio-voice-4"),
- document.getElementById("lcolonq-audio-voice-5"),
- document.getElementById("lcolonq-audio-voice-6"),
- ];
- } catch (e) {
- initialized = false;
- }
- }
-}
-
-export const _playVoice = (b) => (i) => () => {
- if (b) initializeCtx();
- try {
- if (initialized) voiceTracks[i].play();
- } catch (e) {}
-};
diff --git a/fig-frontend-client/src/Audio.purs b/fig-frontend-client/src/Audio.purs
deleted file mode 100644
index 8f1f319..0000000
--- a/fig-frontend-client/src/Audio.purs
+++ /dev/null
@@ -1,10 +0,0 @@
-module Audio where
-
-import Prelude
-
-import Effect (Effect)
-import Effect.Class (class MonadEffect, liftEffect)
-
-foreign import _playVoice :: Boolean -> Int -> Effect Unit
-playVoice :: forall m. MonadEffect m => Boolean -> Int -> m Unit
-playVoice b i = liftEffect $ _playVoice b i
diff --git a/fig-frontend-client/src/Auth.js b/fig-frontend-client/src/Auth.js
deleted file mode 100644
index 7254c40..0000000
--- a/fig-frontend-client/src/Auth.js
+++ /dev/null
@@ -1,45 +0,0 @@
-function generateNonce() {
- var arr = new Uint8Array(20);
- window.crypto.getRandomValues(arr);
- return Array.from(arr, b => b.toString(16).padStart(2, "0")).join("");
-}
-
-export const _startTwitchAuth = (clientID) => (redirectURL) => () => {
- const nonce = generateNonce();
- document.cookie = `authnonce=${nonce}; path=/; max-age=3000`;
- window.location.href =
- `https://id.twitch.tv/oauth2/authorize?response_type=id_token`
- + `&client_id=${clientID}`
- + `&redirect_uri=${redirectURL}`
- + `&scope=openid`
- + `&nonce=${nonce}`
- + `&claims=${JSON.stringify({id_token: {preferred_username: null}})}`
- ;
-};
-
-function getFragmentQuery() {
- let query = new Map();
- const hashQuery = document.location.hash.slice(1).split("&");
- for (let equals of hashQuery) {
- const pair = equals.split("=");
- query.set(decodeURIComponent(pair[0]), decodeURIComponent(pair[1]));
- }
- return query;
-}
-
-export const _getToken = (Just) => (Nothing) => (pair) => () => {
- const frag = getFragmentQuery();
- const token = frag.get("id_token");
- if (token) {
- document.cookie = `id_token=${token}; path=/; SameSite=Strict`;
- }
- let id_token = null;
- let authnonce = null;
- for (let c of document.cookie.split("; ")) {
- const [k, v] = c.split("=");
- if (k === "id_token") id_token = v;
- else if (k === "authnonce") authnonce = v;
- }
- if (id_token && authnonce) return Just(pair(id_token)(authnonce));
- return Nothing;
-};
diff --git a/fig-frontend-client/src/Auth.purs b/fig-frontend-client/src/Auth.purs
deleted file mode 100644
index 2a53629..0000000
--- a/fig-frontend-client/src/Auth.purs
+++ /dev/null
@@ -1,29 +0,0 @@
-module Auth where
-
-import Prelude
-
-import Config (authRedirectURL, clientID)
-import Data.Array (fold)
-import Data.Maybe (Maybe(..))
-import Data.Tuple (Tuple(..))
-import Effect (Effect)
-import Effect.Class (class MonadEffect, liftEffect)
-
-foreign import _startTwitchAuth :: String -> String -> Effect Unit
-startTwitchAuth :: forall m. MonadEffect m => m Unit
-startTwitchAuth = liftEffect $ _startTwitchAuth clientID authRedirectURL
-
-type AuthInfo = Tuple String String
-foreign import _getToken :: forall a. (a -> Maybe a) -> Maybe a -> (a -> a -> Tuple a a) -> Effect (Maybe (Tuple String String))
-getToken :: forall m. MonadEffect m => m (Maybe AuthInfo)
-getToken = liftEffect $ _getToken Just Nothing Tuple
-
-authHeader :: AuthInfo -> String
-authHeader (Tuple t n) =
- fold
- [ "FIG-TWITCH token=\""
- , t
- , "\", nonce=\""
- , n
- , "\""
- ]
diff --git a/fig-frontend-client/src/Config.js b/fig-frontend-client/src/Config.js
deleted file mode 100644
index 25259c7..0000000
--- a/fig-frontend-client/src/Config.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export const mode = globalThis.mode;
-export const apiServer = globalThis.apiServer;
-export const clientID = globalThis.clientID;
-export const authRedirectURL = globalThis.authRedirectURL;
diff --git a/fig-frontend-client/src/Config.purs b/fig-frontend-client/src/Config.purs
deleted file mode 100644
index 536f163..0000000
--- a/fig-frontend-client/src/Config.purs
+++ /dev/null
@@ -1,6 +0,0 @@
-module Config where
-
-foreign import mode :: Int
-foreign import apiServer :: String
-foreign import clientID :: String
-foreign import authRedirectURL :: String
diff --git a/fig-frontend-client/src/Main.purs b/fig-frontend-client/src/Main.purs
deleted file mode 100644
index 48a6e9d..0000000
--- a/fig-frontend-client/src/Main.purs
+++ /dev/null
@@ -1,156 +0,0 @@
-module Main where
-
-import Prelude
-
-import Audio as Audio
-import Auth (AuthInfo, authHeader, getToken, startTwitchAuth)
-import Config as Config
-import Data.Array (head)
-import Data.Array as Array
-import Data.Foldable (fold)
-import Data.Maybe (Maybe(..))
-import Data.Traversable (for, for_)
-import Data.Tuple (Tuple(..))
-import Effect (Effect)
-import Effect.Aff (Aff, launchAff_)
-import Effect.Class (class MonadEffect, liftEffect)
-import Effect.Console (log)
-import Effect.Exception (throw)
-import Fetch (fetch)
-import Model (startModel)
-import UI as UI
-import Web.DOM as DOM
-import Web.DOM.DOMTokenList as DOM.DTL
-import Web.DOM.Document (doctype)
-import Web.DOM.Document as DOM.Doc
-import Web.DOM.Element as DOM.El
-import Web.DOM.Node as DOM.Node
-import Web.DOM.NodeList as DOM.NL
-import Web.DOM.NonElementParentNode as DOM.NEP
-import Web.DOM.ParentNode as DOM.P
-import Web.DOM.Text as DOM.Text
-import Web.Event.Event as Ev
-import Web.Event.EventTarget as Ev.Tar
-import Web.HTML as HTML
-import Web.HTML.HTMLDocument as HTML.Doc
-import Web.HTML.Window as HTML.Win
-
-maybeToArray :: forall a. Maybe a -> Array a
-maybeToArray (Just x) = [x]
-maybeToArray Nothing = []
-
-byId :: forall m. MonadEffect m => String -> m DOM.Element
-byId i = do
- w <- liftEffect HTML.window
- d <- liftEffect $ HTML.Doc.toDocument <$> HTML.Win.document w
- liftEffect (DOM.NEP.getElementById i (DOM.Doc.toNonElementParentNode d)) >>= case _ of
- Nothing -> liftEffect $ throw $ "could not find element with id: " <> i
- Just e -> pure e
-
-queryAll :: forall m. MonadEffect m => String -> m (Array DOM.Element)
-queryAll q = do
- w <- liftEffect HTML.window
- d <- liftEffect $ HTML.Doc.toDocument <$> HTML.Win.document w
- nl <- liftEffect (DOM.P.querySelectorAll (DOM.P.QuerySelector q) (DOM.Doc.toParentNode d))
- ns <- liftEffect $ DOM.NL.toArray nl
- pure $ fold $ (maybeToArray <<< DOM.El.fromNode) <$> ns
-
-query :: forall m . MonadEffect m => String -> m DOM.Element
-query q = do
- queryAll q >>= head >>> case _ of
- Nothing -> liftEffect $ throw $ "could not find element matching query: " <> q
- Just x -> pure x
-
-listen :: forall m. MonadEffect m => DOM.Element -> String -> (Ev.Event -> Effect Unit) -> m Unit
-listen e ev f = do
- l <- liftEffect $ Ev.Tar.eventListener f
- liftEffect $ Ev.Tar.addEventListener (Ev.EventType ev) l false $ DOM.El.toEventTarget e
-
-create :: forall m. MonadEffect m => String -> Array String -> Array DOM.Element -> m DOM.Element
-create tag classes children = do
- w <- liftEffect HTML.window
- d <- liftEffect $ HTML.Doc.toDocument <$> HTML.Win.document w
- el <- liftEffect $ DOM.Doc.createElement tag d
- cl <- liftEffect $ DOM.El.classList el
- for_ classes \c ->
- liftEffect $ DOM.DTL.add cl c
- for_ children \c ->
- appendElement el c
- pure el
-
-appendElement :: forall m. MonadEffect m => DOM.Element -> DOM.Element -> m Unit
-appendElement parent child = liftEffect $ DOM.Node.appendChild (DOM.El.toNode child) (DOM.El.toNode parent)
-
-appendText :: forall m. MonadEffect m => DOM.Element -> String -> m Unit
-appendText parent s = do
- w <- liftEffect HTML.window
- d <- liftEffect $ HTML.Doc.toDocument <$> HTML.Win.document w
- n <- liftEffect $ DOM.Doc.createTextNode s d
- liftEffect $ DOM.Node.appendChild (DOM.Text.toNode n) (DOM.El.toNode parent)
-
-setText :: forall m. MonadEffect m => DOM.Element -> String -> m Unit
-setText e s = liftEffect $ DOM.Node.setTextContent s $ DOM.El.toNode e
-
-updateSubtitle :: Aff Unit
-updateSubtitle = do
- subtitle <- byId "lcolonq-subtitle"
- { text: catchphrase } <- fetch (Config.apiServer <> "/catchphrase") {}
- catchphrase >>= setText subtitle
-
-checkAuth :: AuthInfo -> Aff String
-checkAuth auth = do
- { text: resp } <-
- fetch (Config.apiServer <> "/check")
- { headers:
- { "Authorization": authHeader auth
- }
- }
- resp
-
-mainHomepage :: Effect Unit
-mainHomepage = launchAff_ do
- liftEffect $ log "hi"
- startModel
- marq <- byId "lcolonq-marquee"
- { text: motd } <- fetch (Config.apiServer <> "/motd") {}
- motd >>= setText marq
-
- getToken >>= case _ of
- Just a@(Tuple t n) -> do
- liftEffect $ log t
- liftEffect $ log n
- checkAuth a >>= log >>> liftEffect
- _ -> pure unit
-
- updateSubtitle
- subtitle <- byId "lcolonq-subtitle"
- listen subtitle "click" \_ev -> do
- startTwitchAuth
- launchAff_ updateSubtitle
-
- for_ (Array.range 0 6) \i -> do
- letter <- byId $ "lcolonq-letter-" <> show i
- listen letter "click" \_ev -> do
- Audio.playVoice true i
- listen letter "mouseover" \_ev -> do
- Audio.playVoice false i
-
-mainExtension :: Effect Unit
-mainExtension = launchAff_ do
- liftEffect $ log "hello from extension"
- UI.setInterval 1000.0 do
- e <- query ".chat-scrollable-area__message-container"
- new <- create "div" [".chat-line__message"] []
- appendText new "test"
- appendElement e new
-
-mainObs :: Effect Unit
-mainObs = launchAff_ do
- startModel
-
-main :: Effect Unit
-main = case Config.mode of
- 0 -> mainHomepage
- 1 -> mainExtension
- 2 -> mainObs
- _ -> throw "unknown mode"
diff --git a/fig-frontend-client/src/Model.js b/fig-frontend-client/src/Model.js
deleted file mode 100644
index 797bae4..0000000
--- a/fig-frontend-client/src/Model.js
+++ /dev/null
@@ -1,108 +0,0 @@
-let canvas = document.getElementById("lcolonq-canvas");
-let socket = null;
-let currentFrame = null;
-
-async function decompress(blob) {
- let ds = new DecompressionStream("gzip");
- let stream = blob.stream();
- let out = await new Response(stream.pipeThrough(ds));
- return out.arrayBuffer();
-}
-
-function readCell(dv, base) {
- let cell = {};
- let o = base;
- if (dv.getUint8(o) == 0) {
- return [{type: "bg"}, o + 1];
- } else {
- cell.type = "fg";
- cell.custom = dv.getUint8(o + 1);
- cell.r = dv.getUint8(o + 2);
- cell.g = dv.getUint8(o + 3);
- cell.b = dv.getUint8(o + 4);
- cell.g0 = dv.getUint32(o + 5);
- if (dv.getUint8(o + 9) == 0) {
- return [cell, o + 10];
- } else {
- cell.g1 = dv.getUint32(o + 10);
- return [cell, o + 14];
- }
- }
-}
-
-function readKeyframe(dv, base) {
- let ret = [];
- let o = base;
- for (let idx = 0; idx < (64 * 64); ++idx) {
- let res = readCell(dv, o);
- ret.push(res[0]);
- o = res[1];
- }
- currentFrame = ret;
-}
-
-function readDiff(dv, base) {
- if (currentFrame) {
- let len = dv.getUint32(base);
- let o = base + 4;
- for (let idx = 0; idx < len; ++idx) {
- let x = dv.getUint8(o);
- let y = dv.getUint8(o + 1);
- let c = readCell(dv, o + 2);
- currentFrame[x + (y * 64)] = c[0];
- o = c[1];
- }
- }
-}
-
-function readPacket(dv) {
- if (dv.getUint8(0) == 0) {
- readKeyframe(dv, 1);
- } else {
- readDiff(dv, 1);
- }
-}
-
-function renderCellCanvas(ctx, x, y, c) {
- if (c && c.type === "fg") {
- let msg = c.g1 ? String.fromCodePoint(c.g0, c.g1) : String.fromCodePoint(c.g0);
- if (msg.trim().length) {
- ctx.fillStyle = "black";
- ctx.fillRect(13 * y, 13 * x, 13, 13);
- ctx.fillStyle = `rgba(${c.r}, ${c.g}, ${c.b}, 1.0)`;
- ctx.fillText(msg, 13 * y, 13 * x + 10);
- }
- }
-}
-
-function renderCanvas() {
- if (canvas.width != canvas.clientWidth) {
- canvas.width = canvas.clientWidth;
- }
- if (canvas.height != canvas.clientHeight) {
- canvas.height = canvas.clientHeight;
- }
- if (currentFrame) {
- let ctx = canvas.getContext("2d");
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.font = "12px Iosevka Comfy";
- for (let y = 0; y < 64; ++y) {
- for (let x = 0; x < 64; ++x) {
- renderCellCanvas(ctx, x, y, currentFrame[(x * 64) + y]);
- }
- }
- }
-}
-
-export const _startModel = () => {
- socket = new WebSocket("wss://colonq.computer/bullfrog/api/channel/listen/model");
- socket.addEventListener("open", (ev) => {
- console.log("connected");
- });
- socket.addEventListener("message", async (ev) => {
- let arr = await decompress(ev.data);
- let view = new DataView(arr);
- readPacket(view);
- renderCanvas();
- });
-};
diff --git a/fig-frontend-client/src/Model.purs b/fig-frontend-client/src/Model.purs
deleted file mode 100644
index a9f2888..0000000
--- a/fig-frontend-client/src/Model.purs
+++ /dev/null
@@ -1,10 +0,0 @@
-module Model where
-
-import Prelude
-
-import Effect (Effect)
-import Effect.Class (class MonadEffect, liftEffect)
-
-foreign import _startModel :: Effect Unit
-startModel :: forall m. MonadEffect m => m Unit
-startModel = liftEffect _startModel
diff --git a/fig-frontend-client/src/UI.js b/fig-frontend-client/src/UI.js
deleted file mode 100644
index 0b00e5d..0000000
--- a/fig-frontend-client/src/UI.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export const _cheatLog = (a) => () => console.log(a);
-export const _setInterval = (delay) => (f) => () => setInterval(f, delay);
diff --git a/fig-frontend-client/src/UI.purs b/fig-frontend-client/src/UI.purs
deleted file mode 100644
index 49d797a..0000000
--- a/fig-frontend-client/src/UI.purs
+++ /dev/null
@@ -1,13 +0,0 @@
-module UI where
-
-import Prelude
-import Effect (Effect)
-import Effect.Class (class MonadEffect, liftEffect)
-
-foreign import _cheatLog :: forall a. a -> Effect Unit
-cheatLog :: forall m a. MonadEffect m => a -> m Unit
-cheatLog x = liftEffect $ _cheatLog x
-
-foreign import _setInterval :: Number -> Effect Unit -> Effect Unit
-setInterval :: forall m. MonadEffect m => Number -> Effect Unit -> m Unit
-setInterval d f = liftEffect $ _setInterval d f