From 5fe7ca30fd15f634322ea5e5d519a54c4f77662f Mon Sep 17 00:00:00 2001 From: Failure Date: Sat, 17 Jan 2026 01:24:48 -0800 Subject: [PATCH] initial commit --- .gitignore | 2 + assets/code.js | 110 ++++++++++++++ assets/index.html | 58 ++++++++ assets/style.css | 218 +++++++++++++++++++++++++++ assets/unscii-16.woff | Bin 0 -> 67300 bytes centcom.go | 338 ++++++++++++++++++++++++++++++++++++++++++ config.example.json | 13 ++ go.mod | 8 + 8 files changed, 747 insertions(+) create mode 100644 .gitignore create mode 100644 assets/code.js create mode 100644 assets/index.html create mode 100644 assets/style.css create mode 100644 assets/unscii-16.woff create mode 100644 centcom.go create mode 100644 config.example.json create mode 100644 go.mod diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84d623e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/messages.db +/config.json \ No newline at end of file diff --git a/assets/code.js b/assets/code.js new file mode 100644 index 0000000..9a21ea1 --- /dev/null +++ b/assets/code.js @@ -0,0 +1,110 @@ +const input = document.getElementById("input") +const display = document.getElementById("displayBody") +const glitch = document.getElementById("glitch") +let lastMessage = undefined +let listener + +const addMessage = (from, content) => { + const tr = document.createElement("tr") + const fromTd = document.createElement("td") + fromTd.innerText = from + fromTd.setAttribute("class", from === "COMP/CON" ? "from compcon" : "from") + + const textTd = document.createElement("td") + textTd.innerText = content + textTd.setAttribute("class", "content") + + tr.append(fromTd, textTd) + + display.appendChild(tr) + tr.scrollIntoView() +} + +const makeConnection = () => { + const ws = new WebSocket((window.location.protocol === "https:" ? "wss://" : "ws://") + window.location.host + "/comm") + + ws.onmessage = (msg) => { + const message = JSON.parse(msg.data) + switch (message.type) { + case "error": + addMessage("*", message.content) + break + case "message": + addMessage(message.user, message.content) + break + case "history": + addMessage(message.user, message.content) + break + case "ready": + display.innerHTML = "" + if (lastMessage) { + localStorage.setItem("username", lastMessage) + } + addMessage("*", message.content) + } + } + + ws.onerror = () => { + setTimeout(makeConnection, 1000) + } + ws.onclose = () => { + setTimeout(makeConnection, 1000) + } + + ws.onopen = () => { + if (localStorage.getItem("username")) { + ws.send(JSON.stringify({ + msg: localStorage.getItem("username") + })) + } + } + listener = ws +} + +makeConnection() + + +input.addEventListener("keydown", (e) => { + if (e.key === "Enter" && !e.shiftKey) { + listener.send(JSON.stringify({ + msg: input.innerText + })) + lastMessage = input.innerText + e.preventDefault() + input.innerText = "" + } +}) + +const fun = (pool) => { + const len = Math.ceil(3 + (Math.random() * 15)) + let s = "" + for (let i = 0; i < len; i++) { + s = s + pool.at(Math.floor(Math.random() * pool.length)) + } + return s +} + +const pools = [ + [1, () => ["LIGHT THE FIRES", "green"],], + [5, () => [fun("◯◉"), "cyan"],], + [10, () => [fun("🮗🮖▓▧🮐█🮙▩▥▦🮕▤🮘▨░"), "white"],], + [12, () => ["🯁🯂🯃🮲🮳", "white"]], + [100, () => [fun(" !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ'"), "gray"]], +] + +const spaz = () => { + const r = Math.random() * 100 + for (const [chance, func] of pools) { + if (r < chance) { + const [text, color] = func() + glitch.style.color = color + glitch.innerText = text + break + } + } +} +spaz() + +window.addEventListener("keydown", () => { + spaz() +}) \ No newline at end of file diff --git a/assets/index.html b/assets/index.html new file mode 100644 index 0000000..6a4ad42 --- /dev/null +++ b/assets/index.html @@ -0,0 +1,58 @@ + + + + + CENTCOM + + + + +
+
+ +
+
+LICENSE OWNER: 
+RELEASE:
+TRIAL EXPIRY:
+COMPCON BUILD: 
+
+
TODD (EVALUATION COPY)
+
234-22b
+
NaN
+
ERR
+
+
+████◤
+███◤
+██◤
+█◤
+
+
+
+
+ CENTCOM RESOURCES ARE AVAILABLE AT: HANDBOOK + BARONIES + MORE + +
+
+
+ + + + + + + +
*Please enter your callsign. It will be remembered.
+
+
+ > + +
+ + \ No newline at end of file diff --git a/assets/style.css b/assets/style.css new file mode 100644 index 0000000..8249499 --- /dev/null +++ b/assets/style.css @@ -0,0 +1,218 @@ +@font-face { + font-family: "Unscii"; + src: url("unscii-16.woff"); +} + +@keyframes converge { + 0% {text-shadow: rgba(0, 255, 255, 0.8361107273433098) 6.0px 0 0, rgba(253, 72, 253, 0.9569224401158167) -5.0px 0 0;} + 1% {text-shadow: rgba(0, 255, 255, 0.8619150110069808) 5.95px 0 0, rgba(253, 72, 253, 0.9579050158210693) -4.95px 0 0;} + 2% {text-shadow: rgba(0, 255, 255, 0.854336177145079) 5.9px 0 0, rgba(253, 72, 253, 0.8426867483104116) -4.9px 0 0;} + 3% {text-shadow: rgba(0, 255, 255, 0.9236866898385188) 5.85px 0 0, rgba(253, 72, 253, 0.821628447103927) -4.85px 0 0;} + 4% {text-shadow: rgba(0, 255, 255, 0.8585164669305969) 5.8px 0 0, rgba(253, 72, 253, 0.9886992839559834) -4.8px 0 0;} + 5% {text-shadow: rgba(0, 255, 255, 0.8219830480816586) 5.75px 0 0, rgba(253, 72, 253, 0.9484480449115142) -4.75px 0 0;} + 6% {text-shadow: rgba(0, 255, 255, 0.8003809923844546) 5.7px 0 0, rgba(253, 72, 253, 0.8487031108723073) -4.7px 0 0;} + 7% {text-shadow: rgba(0, 255, 255, 0.8219776552014745) 5.65px 0 0, rgba(253, 72, 253, 0.9113050127726174) -4.65px 0 0;} + 8% {text-shadow: rgba(0, 255, 255, 0.9183556894624699) 5.6px 0 0, rgba(253, 72, 253, 0.8550701555053435) -4.6px 0 0;} + 9% {text-shadow: rgba(0, 255, 255, 0.805410457966203) 5.55px 0 0, rgba(253, 72, 253, 0.8329987799719435) -4.55px 0 0;} + 10% {text-shadow: rgba(0, 255, 255, 0.8398715925070842) 5.5px 0 0, rgba(253, 72, 253, 0.9482139656058877) -4.5px 0 0;} + 11% {text-shadow: rgba(0, 255, 255, 0.967386840612134) 5.45px 0 0, rgba(253, 72, 253, 0.8766333722942649) -4.45px 0 0;} + 12% {text-shadow: rgba(0, 255, 255, 0.897129710183972) 5.4px 0 0, rgba(253, 72, 253, 0.8057922325743391) -4.4px 0 0;} + 13% {text-shadow: rgba(0, 255, 255, 0.9053727693999201) 5.35px 0 0, rgba(253, 72, 253, 0.9054686470293101) -4.35px 0 0;} + 14% {text-shadow: rgba(0, 255, 255, 0.82040606118395) 5.3px 0 0, rgba(253, 72, 253, 0.8027565893856392) -4.3px 0 0;} + 15% {text-shadow: rgba(0, 255, 255, 0.9088155190766086) 5.25px 0 0, rgba(253, 72, 253, 0.8311901733209509) -4.25px 0 0;} + 16% {text-shadow: rgba(0, 255, 255, 0.830204171315196) 5.2px 0 0, rgba(253, 72, 253, 0.8610423937277876) -4.2px 0 0;} + 17% {text-shadow: rgba(0, 255, 255, 0.9993440956157889) 5.15px 0 0, rgba(253, 72, 253, 0.8785756628537958) -4.15px 0 0;} + 18% {text-shadow: rgba(0, 255, 255, 0.8440951076104983) 5.1px 0 0, rgba(253, 72, 253, 0.8367897342791965) -4.1px 0 0;} + 19% {text-shadow: rgba(0, 255, 255, 0.8794669548632236) 5.05px 0 0, rgba(253, 72, 253, 0.8658150502454226) -4.05px 0 0;} + 20% {text-shadow: rgba(0, 255, 255, 0.8296208755041845) 5.0px 0 0, rgba(253, 72, 253, 0.8508951332041956) -4.0px 0 0;} + 21% {text-shadow: rgba(0, 255, 255, 0.9374895228216961) 4.95px 0 0, rgba(253, 72, 253, 0.9407681729537316) -3.95px 0 0;} + 22% {text-shadow: rgba(0, 255, 255, 0.9472441467097896) 4.9px 0 0, rgba(253, 72, 253, 0.8108230906405419) -3.9px 0 0;} + 23% {text-shadow: rgba(0, 255, 255, 0.8841608212385841) 4.85px 0 0, rgba(253, 72, 253, 0.9467742323921511) -3.8499999999999996px 0 0;} + 24% {text-shadow: rgba(0, 255, 255, 0.9857281595178842) 4.8px 0 0, rgba(253, 72, 253, 0.983746771430065) -3.8px 0 0;} + 25% {text-shadow: rgba(0, 255, 255, 0.8901276017385813) 4.75px 0 0, rgba(253, 72, 253, 0.9006720333978879) -3.75px 0 0;} + 26% {text-shadow: rgba(0, 255, 255, 0.8420623794073254) 4.7px 0 0, rgba(253, 72, 253, 0.841030258954916) -3.7px 0 0;} + 27% {text-shadow: rgba(0, 255, 255, 0.80500475794336) 4.65px 0 0, rgba(253, 72, 253, 0.8719997374695452) -3.65px 0 0;} + 28% {text-shadow: rgba(0, 255, 255, 0.8263800795911168) 4.6px 0 0, rgba(253, 72, 253, 0.9560571433379201) -3.5999999999999996px 0 0;} + 29% {text-shadow: rgba(0, 255, 255, 0.9522238613350336) 4.55px 0 0, rgba(253, 72, 253, 0.8677264298768816) -3.55px 0 0;} + 30% {text-shadow: rgba(0, 255, 255, 0.8633010908515628) 4.5px 0 0, rgba(253, 72, 253, 0.8370655185763168) -3.5px 0 0;} + 31% {text-shadow: rgba(0, 255, 255, 0.833147207138388) 4.45px 0 0, rgba(253, 72, 253, 0.9032649254449511) -3.45px 0 0;} + 32% {text-shadow: rgba(0, 255, 255, 0.911593155082442) 4.4px 0 0, rgba(253, 72, 253, 0.9704127292549265) -3.4px 0 0;} + 33% {text-shadow: rgba(0, 255, 255, 0.8730770169688556) 4.35px 0 0, rgba(253, 72, 253, 0.8418315619280776) -3.3499999999999996px 0 0;} + 34% {text-shadow: rgba(0, 255, 255, 0.8254344860492141) 4.3px 0 0, rgba(253, 72, 253, 0.945122258350945) -3.3px 0 0;} + 35% {text-shadow: rgba(0, 255, 255, 0.8994536950486153) 4.25px 0 0, rgba(253, 72, 253, 0.9635174671899864) -3.25px 0 0;} + 36% {text-shadow: rgba(0, 255, 255, 0.8059786830820536) 4.2px 0 0, rgba(253, 72, 253, 0.8107823840459341) -3.2px 0 0;} + 37% {text-shadow: rgba(0, 255, 255, 0.8356685072101536) 4.15px 0 0, rgba(253, 72, 253, 0.8490396342365222) -3.15px 0 0;} + 38% {text-shadow: rgba(0, 255, 255, 0.870306753026597) 4.1px 0 0, rgba(253, 72, 253, 0.8684046884770916) -3.0999999999999996px 0 0;} + 39% {text-shadow: rgba(0, 255, 255, 0.829512957206739) 4.05px 0 0, rgba(253, 72, 253, 0.920924832912171) -3.05px 0 0;} + 40% {text-shadow: rgba(0, 255, 255, 0.981042227568678) 4.0px 0 0, rgba(253, 72, 253, 0.8478604614587707) -3.0px 0 0;} + 41% {text-shadow: rgba(0, 255, 255, 0.9028953642095886) 3.9499999999999997px 0 0, rgba(253, 72, 253, 0.9836375058993726) -2.9499999999999997px 0 0;} + 42% {text-shadow: rgba(0, 255, 255, 0.8298506090024876) 3.9px 0 0, rgba(253, 72, 253, 0.8122960604729693) -2.9px 0 0;} + 43% {text-shadow: rgba(0, 255, 255, 0.9574737190797513) 3.85px 0 0, rgba(253, 72, 253, 0.8207214451650879) -2.85px 0 0;} + 44% {text-shadow: rgba(0, 255, 255, 0.9912354008852822) 3.8px 0 0, rgba(253, 72, 253, 0.9258944470696935) -2.8px 0 0;} + 45% {text-shadow: rgba(0, 255, 255, 0.964617559155446) 3.75px 0 0, rgba(253, 72, 253, 0.8413653094926936) -2.75px 0 0;} + 46% {text-shadow: rgba(0, 255, 255, 0.8556860472070148) 3.6999999999999997px 0 0, rgba(253, 72, 253, 0.8039703790715326) -2.6999999999999997px 0 0;} + 47% {text-shadow: rgba(0, 255, 255, 0.9786225078037258) 3.65px 0 0, rgba(253, 72, 253, 0.8532601491001363) -2.65px 0 0;} + 48% {text-shadow: rgba(0, 255, 255, 0.8136939294439446) 3.5999999999999996px 0 0, rgba(253, 72, 253, 0.9066287030351223) -2.5999999999999996px 0 0;} + 49% {text-shadow: rgba(0, 255, 255, 0.9115638029179485) 3.55px 0 0, rgba(253, 72, 253, 0.8155810075227841) -2.55px 0 0;} + 50% {text-shadow: rgba(0, 255, 255, 0.8486201913333553) 3.5px 0 0, rgba(253, 72, 253, 0.8457649243118975) -2.5px 0 0;} + 51% {text-shadow: rgba(0, 255, 255, 0.8414566201644388) 3.4499999999999997px 0 0, rgba(253, 72, 253, 0.9361224309069724) -2.4499999999999997px 0 0;} + 52% {text-shadow: rgba(0, 255, 255, 0.8359647720401094) 3.4px 0 0, rgba(253, 72, 253, 0.8149059343179613) -2.4px 0 0;} + 53% {text-shadow: rgba(0, 255, 255, 0.9116885963738237) 3.3499999999999996px 0 0, rgba(253, 72, 253, 0.8478810737968121) -2.3499999999999996px 0 0;} + 54% {text-shadow: rgba(0, 255, 255, 0.9156512221006986) 3.3px 0 0, rgba(253, 72, 253, 0.8255903859323139) -2.3px 0 0;} + 55% {text-shadow: rgba(0, 255, 255, 0.8153528842487034) 3.25px 0 0, rgba(253, 72, 253, 0.8994146728664133) -2.25px 0 0;} + 56% {text-shadow: rgba(0, 255, 255, 0.8635217426110132) 3.1999999999999997px 0 0, rgba(253, 72, 253, 0.8100068480800539) -2.1999999999999997px 0 0;} + 57% {text-shadow: rgba(0, 255, 255, 0.8694106443899178) 3.15px 0 0, rgba(253, 72, 253, 0.8650065669920302) -2.15px 0 0;} + 58% {text-shadow: rgba(0, 255, 255, 0.9205282486640333) 3.0999999999999996px 0 0, rgba(253, 72, 253, 0.9146371017699718) -2.0999999999999996px 0 0;} + 59% {text-shadow: rgba(0, 255, 255, 0.9216335826736727) 3.05px 0 0, rgba(253, 72, 253, 0.9535489883131107) -2.05px 0 0;} + 60% {text-shadow: rgba(0, 255, 255, 0.8678550560876669) 3.0px 0 0, rgba(253, 72, 253, 0.9922895844184012) -2.0px 0 0;} + 61% {text-shadow: rgba(0, 255, 255, 0.8047208304855602) 2.9499999999999997px 0 0, rgba(253, 72, 253, 0.8072053478662209) -1.9499999999999997px 0 0;} + 62% {text-shadow: rgba(0, 255, 255, 0.8742226362552165) 2.9px 0 0, rgba(253, 72, 253, 0.9882488598219596) -1.9px 0 0;} + 63% {text-shadow: rgba(0, 255, 255, 0.8187279699943009) 2.8499999999999996px 0 0, rgba(253, 72, 253, 0.847193828631679) -1.8499999999999996px 0 0;} + 64% {text-shadow: rgba(0, 255, 255, 0.915873594484333) 2.8px 0 0, rgba(253, 72, 253, 0.9951780311982585) -1.7999999999999998px 0 0;} + 65% {text-shadow: rgba(0, 255, 255, 0.9091957667405316) 2.75px 0 0, rgba(253, 72, 253, 0.9785125139107118) -1.75px 0 0;} + 66% {text-shadow: rgba(0, 255, 255, 0.9732074805184896) 2.6999999999999997px 0 0, rgba(253, 72, 253, 0.8549161753597928) -1.6999999999999997px 0 0;} + 67% {text-shadow: rgba(0, 255, 255, 0.9942565533650556) 2.65px 0 0, rgba(253, 72, 253, 0.8763648231855105) -1.65px 0 0;} + 68% {text-shadow: rgba(0, 255, 255, 0.9965568662919517) 2.5999999999999996px 0 0, rgba(253, 72, 253, 0.9761753235501034) -1.5999999999999996px 0 0;} + 69% {text-shadow: rgba(0, 255, 255, 0.955938836304943) 2.55px 0 0, rgba(253, 72, 253, 0.9003910147622634) -1.5499999999999998px 0 0;} + 70% {text-shadow: rgba(0, 255, 255, 0.9485273044201737) 2.5px 0 0, rgba(253, 72, 253, 0.9807777183990174) -1.5px 0 0;} + 71% {text-shadow: rgba(0, 255, 255, 0.9674912652650286) 2.4499999999999997px 0 0, rgba(253, 72, 253, 0.9022210932456923) -1.4499999999999997px 0 0;} + 72% {text-shadow: rgba(0, 255, 255, 0.9717372249876183) 2.4px 0 0, rgba(253, 72, 253, 0.8765635698101958) -1.4px 0 0;} + 73% {text-shadow: rgba(0, 255, 255, 0.9645985514947042) 2.3499999999999996px 0 0, rgba(253, 72, 253, 0.8633552189493626) -1.3499999999999996px 0 0;} + 74% {text-shadow: rgba(0, 255, 255, 0.9930937453603206) 2.3px 0 0, rgba(253, 72, 253, 0.8051761331103191) -1.2999999999999998px 0 0;} + 75% {text-shadow: rgba(0, 255, 255, 0.9967694300664716) 2.25px 0 0, rgba(253, 72, 253, 0.8850713876932538) -1.25px 0 0;} + 76% {text-shadow: rgba(0, 255, 255, 0.857931878599814) 2.1999999999999997px 0 0, rgba(253, 72, 253, 0.9484567518701348) -1.1999999999999997px 0 0;} + 77% {text-shadow: rgba(0, 255, 255, 0.8065303268761479) 2.15px 0 0, rgba(253, 72, 253, 0.9861716026231071) -1.15px 0 0;} + 78% {text-shadow: rgba(0, 255, 255, 0.8797138323979175) 2.0999999999999996px 0 0, rgba(253, 72, 253, 0.9327605217362944) -1.0999999999999996px 0 0;} + 79% {text-shadow: rgba(0, 255, 255, 0.8064192594575359) 2.05px 0 0, rgba(253, 72, 253, 0.9752686628797701) -1.0499999999999998px 0 0;} + 80% {text-shadow: rgba(0, 255, 255, 0.8578695134814783) 2.0px 0 0, rgba(253, 72, 253, 0.9597123400872934) -1.0px 0 0;} + 81% {text-shadow: rgba(0, 255, 255, 0.8465689527222937) 1.9500000000000002px 0 0, rgba(253, 72, 253, 0.9362544272288554) -0.9500000000000002px 0 0;} + 82% {text-shadow: rgba(0, 255, 255, 0.9600859379791397) 1.8999999999999995px 0 0, rgba(253, 72, 253, 0.9445462866232998) -0.8999999999999995px 0 0;} + 83% {text-shadow: rgba(0, 255, 255, 0.9741472675714937) 1.8499999999999996px 0 0, rgba(253, 72, 253, 0.9979583491429695) -0.8499999999999996px 0 0;} + 84% {text-shadow: rgba(0, 255, 255, 0.8522887397519873) 1.7999999999999998px 0 0, rgba(253, 72, 253, 0.8642087114124946) -0.7999999999999998px 0 0;} + 85% {text-shadow: rgba(0, 255, 255, 0.8935576284804552) 1.75px 0 0, rgba(253, 72, 253, 0.9995037786832606) -0.75px 0 0;} + 86% {text-shadow: rgba(0, 255, 255, 0.9591551924825271) 1.7000000000000002px 0 0, rgba(253, 72, 253, 0.8895031911672213) -0.7000000000000002px 0 0;} + 87% {text-shadow: rgba(0, 255, 255, 0.847221976351772) 1.6499999999999995px 0 0, rgba(253, 72, 253, 0.8897083979984515) -0.6499999999999995px 0 0;} + 88% {text-shadow: rgba(0, 255, 255, 0.982831513382503) 1.5999999999999996px 0 0, rgba(253, 72, 253, 0.8938824711432813) -0.5999999999999996px 0 0;} + 89% {text-shadow: rgba(0, 255, 255, 0.8543613277389507) 1.5499999999999998px 0 0, rgba(253, 72, 253, 0.9537350423795994) -0.5499999999999998px 0 0;} + 90% {text-shadow: rgba(0, 255, 255, 0.893017776047433) 1.5px 0 0, rgba(253, 72, 253, 0.9956040213561244) -0.5px 0 0;} + 91% {text-shadow: rgba(0, 255, 255, 0.9679434395903915) 1.4500000000000002px 0 0, rgba(253, 72, 253, 0.8782724557074016) -0.4500000000000002px 0 0;} + 92% {text-shadow: rgba(0, 255, 255, 0.8726705168167862) 1.3999999999999995px 0 0, rgba(253, 72, 253, 0.8826217500327997) -0.39999999999999947px 0 0;} + 93% {text-shadow: rgba(0, 255, 255, 0.9966087235235863) 1.3499999999999996px 0 0, rgba(253, 72, 253, 0.8018138119722085) -0.34999999999999964px 0 0;} + 94% {text-shadow: rgba(0, 255, 255, 0.9491747745601509) 1.2999999999999998px 0 0, rgba(253, 72, 253, 0.829179137123354) -0.2999999999999998px 0 0;} + 95% {text-shadow: rgba(0, 255, 255, 0.9127441956297994) 1.25px 0 0, rgba(253, 72, 253, 0.8577438912497287) -0.25px 0 0;} + 96% {text-shadow: rgba(0, 255, 255, 0.9301915605785521) 1.1999999999999993px 0 0, rgba(253, 72, 253, 0.8271745353254621) -0.1999999999999993px 0 0;} + 97% {text-shadow: rgba(0, 255, 255, 0.8860706345525079) 1.1499999999999995px 0 0, rgba(253, 72, 253, 0.9882951178389682) -0.14999999999999947px 0 0;} + 98% {text-shadow: rgba(0, 255, 255, 0.8376062092672816) 1.0999999999999996px 0 0, rgba(253, 72, 253, 0.9615234693412842) -0.09999999999999964px 0 0;} + 99% {text-shadow: rgba(0, 255, 255, 0.8046174532158784) 1.0499999999999998px 0 0, rgba(253, 72, 253, 0.8547331608286676) -0.04999999999999982px 0 0;} + 100% { + text-shadow: rgba(0, 255, 255, 0.8492590734360018) 1.0px 0 0, rgba(253, 72, 253, 0.8562549485674519) -0.0px 0 0; + color: rgba(253, 72, 253); + } +} + +* { + box-sizing: border-box; +} + +html, +body { + font-family: Unscii, monospace; + font-size: 16px; + background: #000; + margin: 0; + color: red; + padding: 0; + line-height: 16px; +} + +pre { + font-family: Unscii, monospace; + padding: 0; + margin: 0; +} + + +.header { + display: flex; +} + +.bgWrap { + background: black; +} + +.yellow { + color: #e3f44d; +} + +.logo, .trailerSlide { + background: #1e992a; + color: black; + display: inline; +} + +.trailer { + height: 64px; + background: #1e992a; + flex-grow: 1; +} +@keyframes blink { + 50% { + opacity: 0; + } +} +.syserror { + color: red; + animation: 1s blink step-start infinite; +} + +.display { + height: 256px; + overflow: scroll; +} + +#displayTable { + display: flex; + flex-direction: column; +} + +.cmdinput { + color: white; + display: flex; + flex-direction: row; +} +.cmdinput > span:first-child { + width: 16px; +} + +#input { + flex-grow: 1; + outline: 0; +} + +a, a:link, a:visited { + color: #8686ff; + text-decoration: none; + text-underline: none; +} + +a:link:before { + content: "▹"; +} + +.padder { + height: 230px; +} + +.from { + color: #ff8f02; + text-align: right; + border-right: transparent 8px solid; +} + +.content { + color: white; +} + +.compcon { + animation: converge 1.4s ease-out forwards; +} \ No newline at end of file diff --git a/assets/unscii-16.woff b/assets/unscii-16.woff new file mode 100644 index 0000000000000000000000000000000000000000..ffc98bebd5c5d671fc0a31b1d1173bd7813be97b GIT binary patch literal 67300 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%0D3sMH0O5>ROhDy5;)N2qiNm9C@GLsTw< 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 literal 0 HcmV?d00001 diff --git a/centcom.go b/centcom.go new file mode 100644 index 0000000..9808b39 --- /dev/null +++ b/centcom.go @@ -0,0 +1,338 @@ +package main + +import ( + "bytes" + "database/sql" + "encoding/base64" + "encoding/json" + "flag" + "fmt" + "log" + "net/http" + "os" + "slices" + "strconv" + "strings" + "sync" + "time" + + "github.com/gorilla/websocket" + _ "github.com/mattn/go-sqlite3" +) + +const CONFIGFILE = "./config.json" + +type Client struct { + Conn *websocket.Conn + Name string + Mu sync.Mutex +} + +type Server struct { + Mu sync.Mutex + Clients []*Client + Db *sql.DB + Cef *CEF +} + +type CEF struct { + Conn *websocket.Conn + FromServer chan string + ToServer chan string + Kill chan error +} + +type Message struct { + Type string `json:"type"` + User string `json:"user"` + Content string `json:"content"` +} + +type Config struct { + Listen string `json:"listen"` + Webhook string `json:"webhook"` + Cef struct { + Channel string `json:"channel"` + Username string `json:"username"` + Password string `json:"password"` + } `json:"cef"` + Users []string `json:"users"` +} + +var config Config +var server = Server{ + Clients: make([]*Client, 0), +} + +func (s *Server) KillClient(client *Client) { + s.Mu.Lock() + defer s.Mu.Unlock() + for i, _ := range s.Clients { + if client == s.Clients[i] { + s.Clients = append(s.Clients[:i], s.Clients[i+1:]...) + return + } + } +} + +func (c *Client) Send(struc any) { + c.Mu.Lock() + defer c.Mu.Unlock() + err := c.Conn.WriteJSON(struc) + if err != nil { + server.KillClient(c) + } +} + +func Webhook(message Message) { + jsonValue, _ := json.Marshal(struct { + Content string `json:"content"` + Username string `json:"username"` + }{ + Content: message.Content, + Username: message.User, + }) + _, err := http.Post(config.Webhook, "application/json", bytes.NewBuffer(jsonValue)) + if err != nil { + log.Println("webhook", err) + } +} + +func (s *Server) BroadcastMessage(from string, content string) { + message := Message{ + Type: "message", + User: from, + Content: content, + } + for _, c := range s.Clients { + c.Send(message) + } + tx, err := s.Db.Begin() + stmt, err := tx.Prepare("insert into messages(`type`, `user`, `content`) values(?, ?, ?)") + if err != nil { + log.Fatal(err) + return + } + _, err = stmt.Exec("message", from, content) + if err != nil { + log.Println(stmt) + return + } + tx.Commit() + go Webhook(message) + go s.CEFSend(message) +} + +func (s *Server) CEFSend(message Message) { + msg := fmt.Sprintf("NPC %s %s :%s", config.Cef.Channel, message.User, message.Content) + select { + case s.Cef.ToServer <- msg: + default: + } +} + +func (s *Server) SendHistory(client *Client) { + // Blast + rows, err := s.Db.Query("SELECT `user`, `content` FROM messages ORDER BY rowid ASC") + if err != nil { + log.Println(err) + return + } + defer rows.Close() + var user, content string + + for rows.Next() { + err = rows.Scan(&user, &content) + if err != nil { + log.Panicln(err) + } + client.Send(Message{ + Type: "history", + User: user, + Content: content, + }) + + } + + client.Send(Message{ + Type: "ready", + User: strconv.Itoa(len(server.Clients)), + Content: "Welcome back, " + client.Name, + }) + +} + +func loadConfig() { + data, err := os.ReadFile(CONFIGFILE) + if err != nil { + log.Panicln("Could not read config, ", err) + } + err = json.Unmarshal(data, &config) + if err != nil { + log.Panicln("Could not load config, ", err) + } +} + +func watchConfig() { + initialStat, _ := os.Stat(CONFIGFILE) + + for { + stat, _ := os.Stat(CONFIGFILE) + + if stat.Size() != initialStat.Size() || stat.ModTime() != initialStat.ModTime() { + loadConfig() + } + + time.Sleep(1 * time.Second) + } +} + +func (c *CEF) Send(m string) { + log.Println("[CEF-O]", m) + err := c.Conn.WriteMessage(websocket.TextMessage, []byte(m)) + if err != nil { + log.Println("[CEF-S]", err) + c.Kill <- err + return + } +} + +func (c *CEF) Loop() { + for { + _, message, err := c.Conn.ReadMessage() + log.Println("[CEF]", string(message), err) + if err != nil { + c.Kill <- err + return + } + c.FromServer <- string(message) + } +} + +func BasicCef() { + c, _, err := websocket.DefaultDialer.Dial("wss://cef.icu/chat", nil) + defer c.Close() + if err != nil { + return + } + cef := &CEF{ + Conn: c, + FromServer: make(chan string), + ToServer: make(chan string), + Kill: make(chan error), + } + defer close(cef.FromServer) + defer close(cef.ToServer) + defer close(cef.Kill) + server.Cef = cef + cef.Send("CAP REQ :account-notify account-tag away-notify batch chghost cef/extended-names draft/chathistory draft/multiline draft/event-playback draft/relaymsg echo-message extended-join invite-notify labeled-response message-tags multi-prefix sasl server-time setname userhost-in-names") + cef.Send("NICK " + config.Cef.Username) + cef.Send("USER " + config.Cef.Username + " . . :cool dude") + cef.Send("AUTHENTICATE PLAIN") + auth := fmt.Sprintf("%s\000%s\000%s", config.Cef.Username, config.Cef.Username, config.Cef.Password) + cef.Send("AUTHENTICATE " + base64.StdEncoding.EncodeToString([]byte(auth))) + cef.Send("CAP END") + // cef.Send("JOIN " + config.Cef.Channel) + + go cef.Loop() + for { + select { + case msg := <-cef.FromServer: + split := strings.Split(msg, " ") + if len(split) > 2 { + if split[1] == "PING" { + cef.Send("PONG " + split[2]) + } + } + case msg := <-cef.ToServer: + cef.Send(msg) + case killError := <-cef.Kill: + log.Println("[CEF]", killError) + break + } + } + +} + +var upgrader = websocket.Upgrader{} // use default options + +func comm(w http.ResponseWriter, r *http.Request) { + c, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Print("upgrade:", err) + return + } + defer c.Close() + var client = &Client{ + Conn: c, + Name: "", + } + setup := false + var inbound struct { + Msg string `json:"msg"` + } + for { + _, message, err := c.ReadMessage() + if err != nil { + log.Println("read:", err) + break + } + err = json.Unmarshal(message, &inbound) + if err != nil { + log.Println("unmarshal", err) + return + } + log.Printf("recv: %s", message) + if !setup { + if slices.Contains(config.Users, inbound.Msg) { + server.Mu.Lock() + server.Clients = append(server.Clients, client) + server.Mu.Unlock() + defer server.KillClient(client) + setup = true + client.Name = inbound.Msg + server.SendHistory(client) + } else { + err := c.WriteJSON(Message{ + Type: "error", + User: "", + Content: "LANCER NOT FOUND", + }) + if err != nil { + log.Println("writejson", err) + return + } + } + } else { + server.BroadcastMessage(client.Name, inbound.Msg) + } + } +} + +func CefDaemon() { + for { + BasicCef() + time.Sleep(60) + } +} + +func main() { + loadConfig() + go watchConfig() + var addr = flag.String("addr", config.Listen, "http service address") + db, err := sql.Open("sqlite3", "./messages.db") + if err != nil { + log.Fatal(err) + } + server.Db = db + db.Exec("CREATE TABLE messages(`type` text, `user` text, `content` text)") + defer db.Close() + go CefDaemon() + + flag.Parse() + log.SetFlags(0) + fs := http.FileServer(http.Dir("./assets")) + http.Handle("/", fs) + http.HandleFunc("/comm", comm) + log.Fatal(http.ListenAndServe(*addr, nil)) +} diff --git a/config.example.json b/config.example.json new file mode 100644 index 0000000..6489c48 --- /dev/null +++ b/config.example.json @@ -0,0 +1,13 @@ +{ + "listen": "0.0.0.0:7305", + "webhook": "", + "cef": { + "channel": "#test", + "username": "Centcom", + "password": "Password" + }, + "users": [ + "COMP/CON", + "Guest" + ] +} \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..6a92e87 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module CENTCOM + +go 1.24 + +require ( + github.com/gorilla/websocket v1.5.3 + github.com/mattn/go-sqlite3 v1.14.33 +)