Add web client, update CLI client

This commit is contained in:
Maxwell Jeffress 2024-11-05 20:35:10 +11:00
parent 41c9e7f53f
commit a4b6721ebc
10 changed files with 312 additions and 3 deletions

View File

@ -2,6 +2,8 @@ package xyz.maxwellj.chookpen.client
import okhttp3.*
import java.util.Scanner
import java.util.concurrent.TimeUnit
import kotlin.system.exitProcess
import java.io.File
@ -52,7 +54,7 @@ fun main() {
}
val client = OkHttpClient.Builder()
//.pingInterval(30, TimeUnit.SECONDS)
.pingInterval(30, TimeUnit.SECONDS)
.build()
val request = Request.Builder()

Binary file not shown.

137
client-web/index.css Normal file
View File

@ -0,0 +1,137 @@
@font-face {
font-family: "inter";
src: url("InterVariable.ttf");
}
body {
color: white;
background: rgb(231,255,68);
background: linear-gradient(336deg, rgba(231,255,68,0.67) 0%, rgba(73,255,145,0.67) 43%, rgba(104,79,255,1) 100%);
font-family: inter;
background-attachment: fixed;
margin-left: 20px;
margin-right: 20px;
margin-top: 20px;
margin-bottom: 20px;
}
a {
color: white;
}
input {
color: white;
background: rgba(0, 0, 0, 0.5);
border: none;
border-radius: 10px;
padding: 5px;
font-family: "inter";
margin: 10px;
}
.tiny {
font-size: 5pt;
}
h1 {
font-size: 35pt;
}
h2 {
font-size: 20pt;
}
h3 {
font-size: 15pt;
}
p {
font-size: 12pt;
}
#messagebox {
overflow-y: auto;
border 0px;
padding: 20px;
margin: 10px 10px;
}
.section {
background-color: rgba(0, 0, 0, 0.1);
max-width: 50%;
border-radius: 10px;
margin-top: 10px;
margin-bottom: 10px;
padding: 5px
}
.section h2 {
margin: 20px;
}
.box {
color: white;
background: rgba(0, 0, 0, 0.5);
max-width: 95%;
border-radius: 10px;
margin-top: 10px;
margin-bottom: 10px;
margin-left: auto;
margin-right: auto;
padding: 5px;
}
.box p {
margin: 10px;
}
.box h3 {
margin: 10px;
}
.box img {
margin: 10px;
}
.box button {
margin: 10px;
}
.bluebutton {
color: white;
font-size: 12pt;
background: rgba(0, 0, 255, 0.3);
font-family: inter;
border-radius: 10px;
border: none;
padding: 5px;
}
.greenbutton {
color: white;
font-size: 12pt;
background: rgba(0, 255, 0, 0.3);
font-family: inter;
border-radius: 10px;
border: none;
padding: 5px;
}
.redbutton {
color: white;
font-size: 12pt;
background: rgba(255, 0, 0, 0.3);
font-family: inter;
border-radius: 10px;
border: none;
padding: 5px;
}
.backbutton {
color: white;
font-size: 12pt;
background: rgba(255, 0, 0, 0.3);
font-family: inter;
border-radius: 10px;
border: none;
padding: 5px;
}
.hidden {
display: none;
}

43
client-web/index.html Normal file
View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chookpen</title>
<link type="text/css" rel="stylesheet" href="index.css">
<link rel="shortcut icon" type="image/jpg" href="favicon.ico"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
</head>
<body>
<div id="login">
<div class="section">
<div class="box">
<h3>Chookpen</h3>
<input type="text" id="username" placeholder="Username"><br>
<input type="password" id="password" placeholder="Password"><br>
<button class="bluebutton" onclick="connect()">Log in</button>
<button class="greenbutton" onclick="register()">Register</button>
<button class="redbutton" onclick="showConfig()">Show Server Config</button>
<div id="serverStatus"></div>
</div>
<div class="box" style="display: none;" id="serverconfig">
<input type="text" id="serverUrl" value="bobcompass.online" placeholder="Server URL"><br>
<input type="text" id="serverPort" value="443" placeholder="Server Port"><br>
<input type="checkbox" id="securityStatus" checked>
<label for="securityStatus">Use HTTPS/WSS</label>
</div>
</div>
</div>
<div class="hidden" id="messaging">
<div class="section">
<div class="box">
<h3>Chookpen</h3>
<div id="messagebox" class="box" style="height: 600px;"><div style="color: grey;">Chookpen for Web is ready. Happy chatting!</div></div>
<input type="text" id="messageInput" placeholder="Send a message...">
<button onclick="sendMessage()" class="bluebutton">Send</button>
</div>
</div>
</div>
<script src="index.js"></script>
</body>
</html>

117
client-web/index.js Normal file
View File

@ -0,0 +1,117 @@
alert("Chookpen is currently in early development, expect bugs! Please don't try breaking the public server, do that with your own test server (read more in the Git repo). Thanks for trying Chookpen!")
let ws;
let username;
let password;
function showConfig() {
const serverconfig = document.getElementById('serverconfig')
if (serverconfig) {
serverconfig.style.display = 'block';
}
}
function md5(string) {
return CryptoJS.MD5(string).toString();
}
function getUrl() {
const serverUrl = document.getElementById('serverUrl').value.trim();
const serverPort = document.getElementById('serverPort').value;
const useWss = document.getElementById('securityStatus').checked;
const protocol = useWss ? 'wss' : 'ws';
const cleanUrl = serverUrl.replace(/^(https?:\/\/|wss?:\/\/)/, '');
return `${protocol}://${cleanUrl}:${serverPort}/api/websocket`;
}
function getSignupUrl() {
const serverUrl = document.getElementById('serverUrl').value.trim();
const serverPort = document.getElementById('serverPort').value;
const useWss = document.getElementById('securityStatus').checked;
const protocol = useWss ? 'https' : 'http';
const cleanUrl = serverUrl.replace(/^(https?:\/\/|wss?:\/\/)/, '');
return `${protocol}://${cleanUrl}:${serverPort}/api/createaccount/`;
}
function connect() {
username = document.getElementById('username').value;
password = document.getElementById('password').value;
if (!username || !password) {
alert('Please enter a username and password');
return;
}
const wsUrl = getUrl();
if (ws) {
ws.close();
}
ws = new WebSocket(wsUrl);
ws.onopen = () => {
Notification.requestPermission();
console.log('Connected!');
document.getElementById('login').style.display = 'none';
document.getElementById('messaging').style.display = 'block';
ws.send(`username:{${username}}token:{${md5(password)}}command:{login}commandArg:{${username}}`);
ws.send(`username:{${username}}token:{${md5(password)}}message:{Joined the room}`);
ws.onmessage = (event) => {
if (event.data === "ping") {
ws.send("pong");
return;
}
console.log(event.data);
const messagesDiv = document.getElementById('messagebox');
const messageElement = document.createElement('div');
if (messageElement) {
if (messagesDiv) {
messagesDiv.appendChild(messageElement);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
messageElement.className = 'message';
messageElement.textContent = event.data;
}
}
if (document.hidden) {
const notifiction = new Notification("Chookpen", {body: messageElement.textContent});
}
};
}
}
function sendMessage() {
const messageInput = document.getElementById('messageInput');
const message = messageInput.value.trim();
if (message && ws && ws.readyState === WebSocket.OPEN) {
ws.send(`username:{${username}}token:{${md5(password)}}message:{${message}}`);
messageInput.value = '';
}
}
document.getElementById('messageInput').addEventListener('keypress', (event) => {
if (event.key === 'Enter') {
sendMessage();
}
});
document.getElementById('password').addEventListener('keypress', (event) => {
if (event.key === 'Enter') {
connect();
}
});
function register() {
username = document.getElementById('username').value;
password = document.getElementById('password').value;
if (!username || !password) {
alert('Please enter a username and password');
return;
}
window.open(`${getSignupUrl()}username:{${username}}token:{${md5(password)}}`);
}

View File

@ -13,6 +13,9 @@ import java.io.BufferedReader
import java.math.BigInteger
import java.security.MessageDigest
import java.nio.file.Paths
import java.nio.file.Files
fun md5(input:String): String {
val md = MessageDigest.getInstance("MD5")
return BigInteger(1, md.digest(input.toByteArray())).toString(16).padStart(32, '0')
@ -447,8 +450,11 @@ fun authKey(inputData: String): String {
fun main(args: Array<String>) {
WsSessionManager.peopleOnline.removeAt(0)
WsSessionManager.sessionsList.removeAt(0)
val app = Javalin.create()
.get("/") { ctx -> ctx.result("dingus") }
val app = Javalin.create { config ->
config.staticFiles.add("/public")
}.get("/") { ctx ->
ctx.redirect("/index.html")
}
.get("/api/send/{content}") { ctx ->
val result = handleSentMessage(ctx.pathParam("content"))
if (result == "Success") {

View File

@ -0,0 +1 @@
../../../../../client-web/InterVariable.ttf

View File

@ -0,0 +1 @@
../../../../../client-web/index.css

View File

@ -0,0 +1 @@
../../../../../client-web/index.html

View File

@ -0,0 +1 @@
../../../../../client-web/index.js