2023-05-07 18:43:57 -07:00
|
|
|
function rand() {
|
|
|
|
let str = "";
|
|
|
|
const lookups =
|
|
|
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".split("");
|
|
|
|
while (str.length < 16) {
|
|
|
|
const n = Math.random() * lookups.length;
|
|
|
|
str += lookups[Math.floor(n)];
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function auth() {
|
2023-05-08 22:45:19 -07:00
|
|
|
let session = rand();
|
2023-05-07 18:43:57 -07:00
|
|
|
const sig = await openpgp.sign({
|
2023-05-08 22:45:19 -07:00
|
|
|
message: new openpgp.CleartextMessage("vybe_auth " + session, ""),
|
2023-05-07 18:43:57 -07:00
|
|
|
signingKeys: window.keys.priv,
|
|
|
|
});
|
2023-05-08 22:45:19 -07:00
|
|
|
window.session = session;
|
2023-05-07 18:43:57 -07:00
|
|
|
window.socket.emit("authenticate", { name: window.name, message: sig });
|
|
|
|
}
|
2023-05-05 20:12:07 -07:00
|
|
|
|
2023-05-06 20:55:04 -07:00
|
|
|
async function register(e) {
|
|
|
|
e.preventDefault();
|
2023-05-05 20:12:07 -07:00
|
|
|
const name = document.getElementById("name").value;
|
|
|
|
if (!name) return;
|
|
|
|
const keys = await openpgp.generateKey({
|
|
|
|
userIDs: [{ name }],
|
|
|
|
});
|
|
|
|
const priv = await openpgp.readKey({ armoredKey: keys.privateKey });
|
|
|
|
const pub = await openpgp.readKey({ armoredKey: keys.publicKey });
|
|
|
|
window.keys = { priv, pub };
|
|
|
|
localStorage.setItem("keys", JSON.stringify(keys));
|
|
|
|
localStorage.setItem("name", name);
|
|
|
|
window.name = name;
|
|
|
|
window.socket.emit("create_user", { name, pubkey: keys.publicKey });
|
|
|
|
}
|
|
|
|
|
|
|
|
async function message(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
const msg = document.getElementById("msg").value;
|
|
|
|
if (!msg) return;
|
2023-05-08 21:02:57 -07:00
|
|
|
window.socket.emit("send_message", {
|
|
|
|
message: msg,
|
|
|
|
thread: window.currentThreadId,
|
|
|
|
});
|
2023-05-05 20:12:07 -07:00
|
|
|
document.getElementById("msg").value = "";
|
|
|
|
const el = document.createElement("div");
|
|
|
|
el.classList.add("message");
|
|
|
|
el.innerHTML = `<strong>${window.name}: </strong>${msg}`;
|
|
|
|
document.getElementById("messages").appendChild(el);
|
|
|
|
}
|
|
|
|
|
|
|
|
function swap() {
|
|
|
|
document.getElementById("register").classList.add("hidden");
|
|
|
|
document.getElementById("chat").classList.remove("hidden");
|
|
|
|
}
|
|
|
|
|
2023-05-08 21:02:57 -07:00
|
|
|
function startThreadPicker() {
|
|
|
|
document.getElementById("chat").classList.add("hidden");
|
|
|
|
document.getElementById("threads").classList.remove("hidden");
|
|
|
|
window.socket.emit("list_threads");
|
|
|
|
}
|
|
|
|
|
|
|
|
function chooseThread(thread) {
|
|
|
|
window.currentThreadId = thread.id;
|
|
|
|
window.earliestMessage = null;
|
|
|
|
document.getElementById("loadmore").classList.remove("hidden");
|
|
|
|
document.getElementById("chat").classList.remove("hidden");
|
|
|
|
document.getElementById("messages").innerHTML = "";
|
|
|
|
document.getElementById("threadname").innerHTML = thread.name;
|
|
|
|
document.getElementById("threads").classList.add("hidden");
|
|
|
|
}
|
|
|
|
|
|
|
|
function createThread(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
window.socket.emit("create_thread", {
|
|
|
|
name: document.getElementById("newthreadname").value,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-05-05 20:12:07 -07:00
|
|
|
async function loadKeys(keys) {
|
|
|
|
const priv = await openpgp.readKey({ armoredKey: keys.privateKey });
|
|
|
|
const pub = await openpgp.readKey({ armoredKey: keys.publicKey });
|
|
|
|
window.keys = { priv, pub };
|
2023-05-07 18:43:57 -07:00
|
|
|
await auth();
|
2023-05-05 20:12:07 -07:00
|
|
|
}
|
|
|
|
|
2023-05-05 21:56:59 -07:00
|
|
|
async function loadMessages() {
|
|
|
|
window.socket.emit(
|
|
|
|
"get_history",
|
2023-05-08 21:02:57 -07:00
|
|
|
window.earliestMessage
|
|
|
|
? { before: window.earliestMessage, thread: window.currentThreadId }
|
|
|
|
: { thread: window.currentThreadId }
|
2023-05-05 21:56:59 -07:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-05-05 20:12:07 -07:00
|
|
|
window.onload = () => {
|
2023-05-08 21:02:57 -07:00
|
|
|
window.currentThreadId = 1;
|
2023-05-06 20:55:04 -07:00
|
|
|
window.socket = io();
|
2023-05-07 18:43:57 -07:00
|
|
|
window.socket.on("create_user", auth);
|
2023-05-05 20:12:07 -07:00
|
|
|
window.socket.on("new_message", (msg) => {
|
2023-05-08 21:02:57 -07:00
|
|
|
if (msg.thread !== window.currentThreadId) return;
|
2023-05-05 20:12:07 -07:00
|
|
|
const el = document.createElement("div");
|
|
|
|
el.classList.add("message");
|
|
|
|
el.innerHTML = `<strong>${msg.name}: </strong>${msg.message}`;
|
|
|
|
document.getElementById("messages").appendChild(el);
|
2023-05-05 21:56:59 -07:00
|
|
|
if (!window.earliestMessage) window.earliestMessage = msg.id;
|
|
|
|
});
|
|
|
|
window.socket.on("send_message", (msg) => {
|
|
|
|
if (!window.earliestMessage) window.earliestMessage = msg.id;
|
|
|
|
});
|
|
|
|
window.socket.on("get_history", (msg) => {
|
2023-05-07 21:25:39 -07:00
|
|
|
if (msg.messages.length > 0) {
|
|
|
|
window.earliestMessage = msg.messages[msg.messages.length - 1].id;
|
|
|
|
for (let message of msg.messages) {
|
|
|
|
const el = document.createElement("div");
|
|
|
|
el.classList.add("message");
|
|
|
|
el.innerHTML = `<strong>${message.name}: </strong>${message.message}`;
|
|
|
|
document.getElementById("messages").prepend(el);
|
|
|
|
}
|
2023-05-05 21:56:59 -07:00
|
|
|
}
|
|
|
|
if (!msg.more) document.getElementById("loadmore").classList.add("hidden");
|
2023-05-05 20:12:07 -07:00
|
|
|
});
|
2023-05-08 21:02:57 -07:00
|
|
|
window.socket.on("authenticate", (msg) => {
|
|
|
|
if (msg.success) swap();
|
2023-05-08 22:45:19 -07:00
|
|
|
let emitter = window.socket.emit;
|
|
|
|
window.socket.emit = (type, data) => {
|
|
|
|
if (data)
|
|
|
|
return emitter.call(window.socket, type, {
|
|
|
|
...data,
|
|
|
|
__session: window.session,
|
|
|
|
});
|
|
|
|
else return emitter.call(window.socket, type);
|
|
|
|
};
|
2023-05-08 21:02:57 -07:00
|
|
|
});
|
|
|
|
window.socket.on("list_threads", (msg) => {
|
|
|
|
document.getElementById("threadlist").innerHTML = "";
|
|
|
|
for (let thread of msg.threads) {
|
|
|
|
const el = document.createElement("div");
|
|
|
|
el.classList.add("thread");
|
|
|
|
el.innerHTML = thread.name;
|
|
|
|
const btn = document.createElement("button");
|
|
|
|
btn.innerHTML = "choose";
|
|
|
|
btn.onclick = () => chooseThread(thread);
|
|
|
|
el.appendChild(btn);
|
|
|
|
document.getElementById("threadlist").appendChild(el);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
window.socket.on("create_thread", (msg) => {
|
|
|
|
chooseThread({
|
|
|
|
name: document.getElementById("newthreadname").value,
|
|
|
|
id: msg.id,
|
|
|
|
});
|
|
|
|
document.getElementById("newthreadname").value = "";
|
|
|
|
});
|
2023-05-05 20:12:07 -07:00
|
|
|
const keys = localStorage.getItem("keys");
|
|
|
|
if (keys) {
|
|
|
|
window.name = localStorage.getItem("name");
|
2023-05-07 18:43:57 -07:00
|
|
|
loadKeys(JSON.parse(keys)).then(() => {});
|
2023-05-05 20:12:07 -07:00
|
|
|
}
|
2023-05-06 20:55:04 -07:00
|
|
|
document.getElementById("registerform").onsubmit = register;
|
2023-05-05 20:12:07 -07:00
|
|
|
document.getElementById("msginput").onsubmit = message;
|
2023-05-05 21:56:59 -07:00
|
|
|
document.getElementById("loadmore").onclick = loadMessages;
|
2023-05-08 21:02:57 -07:00
|
|
|
document.getElementById("change").onclick = startThreadPicker;
|
|
|
|
document.getElementById("createthread").onsubmit = createThread;
|
2023-05-05 20:12:07 -07:00
|
|
|
};
|