initial load messages
							parent
							
								
									5e6ce1a210
								
							
						
					
					
						commit
						767c040634
					
				
							
								
								
									
										449
									
								
								client/chat.js
								
								
								
								
							
							
						
						
									
										449
									
								
								client/chat.js
								
								
								
								
							|  | @ -1,127 +1,126 @@ | |||
| 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; | ||||
| 	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() { | ||||
|   let session = rand(); | ||||
|   const sig = await openpgp.sign({ | ||||
|     message: new openpgp.CleartextMessage("vybe_auth " + session, ""), | ||||
|     signingKeys: window.keys.priv, | ||||
|   }); | ||||
|   window.session = session; | ||||
|   window.socket.emit("authenticate", { name: window.name, message: sig }); | ||||
| 	let session = rand(); | ||||
| 	const sig = await openpgp.sign({ | ||||
| 		message: new openpgp.CleartextMessage("vybe_auth " + session, ""), | ||||
| 		signingKeys: window.keys.priv, | ||||
| 	}); | ||||
| 	window.session = session; | ||||
| 	window.socket.emit("authenticate", { name: window.name, message: sig }); | ||||
| } | ||||
| 
 | ||||
| async function loadKeys(keys) { | ||||
|   const priv = await openpgp.readKey({ armoredKey: keys.privateKey }); | ||||
|   const pub = await openpgp.readKey({ armoredKey: keys.publicKey }); | ||||
|   window.keys = { priv, pub }; | ||||
|   await auth(); | ||||
| 	const priv = await openpgp.readKey({ armoredKey: keys.privateKey }); | ||||
| 	const pub = await openpgp.readKey({ armoredKey: keys.publicKey }); | ||||
| 	window.keys = { priv, pub }; | ||||
| 	await auth(); | ||||
| } | ||||
| 
 | ||||
| function chooseThread(thread) { | ||||
|   window.currentThreadId = thread.id; | ||||
|   window.earliestMessage = null; | ||||
|   document.getElementById("messages").innerHTML = ""; | ||||
|   document.getElementById("threadname").innerHTML = thread.name; | ||||
| 	window.currentThreadId = thread.id; | ||||
| 	window.earliestMessage = null; | ||||
| 	document.getElementById("messages").innerHTML = ""; | ||||
| 	document.getElementById("threadname").innerHTML = thread.name; | ||||
| } | ||||
| 
 | ||||
| function loadMessages() { | ||||
|   window.socket.emit("get_history", { | ||||
|     before: window.earliestMessage, | ||||
|     thread: window.currentThreadId, | ||||
|   }); | ||||
| 	window.socket.emit("get_history", { | ||||
| 		before: window.earliestMessage, | ||||
| 		thread: window.currentThreadId, | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function addThread(thread) { | ||||
|   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); | ||||
|     loadMessages(); | ||||
|     document.getElementById("loadmore").classList.remove("hidden"); | ||||
|     if (!thread.permissions.post) { | ||||
|       document.getElementById("msginput").classList.add("hidden"); | ||||
|     } else { | ||||
|       document.getElementById("msginput").classList.remove("hidden"); | ||||
|     } | ||||
|   }; | ||||
|   el.appendChild(btn); | ||||
|   document.getElementById("threadlist").appendChild(el); | ||||
| 	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); | ||||
| 		loadMessages(); | ||||
| 		if (!thread.permissions.post) { | ||||
| 			document.getElementById("msginput").classList.add("hidden"); | ||||
| 		} else { | ||||
| 			document.getElementById("msginput").classList.remove("hidden"); | ||||
| 		} | ||||
| 	}; | ||||
| 	el.appendChild(btn); | ||||
| 	document.getElementById("threadlist").appendChild(el); | ||||
| } | ||||
| 
 | ||||
| function addMember() { | ||||
|   const name = document.getElementById("membername").value; | ||||
|   if (!window.threadmembers) { | ||||
|     window.threadmembers = [window.name, name]; | ||||
|   } else { | ||||
|     window.threadmembers.push(name); | ||||
|   } | ||||
|   const member = document.createElement("p"); | ||||
|   member.textContent = name; | ||||
|   member.classList.add("member"); | ||||
|   document.getElementById("memberlist").appendChild(member); | ||||
|   document.getElementById("membername").value = ""; | ||||
| 	const name = document.getElementById("membername").value; | ||||
| 	if (!window.threadmembers) { | ||||
| 		window.threadmembers = [window.name, name]; | ||||
| 	} else { | ||||
| 		window.threadmembers.push(name); | ||||
| 	} | ||||
| 	const member = document.createElement("p"); | ||||
| 	member.textContent = name; | ||||
| 	member.classList.add("member"); | ||||
| 	document.getElementById("memberlist").appendChild(member); | ||||
| 	document.getElementById("membername").value = ""; | ||||
| } | ||||
| 
 | ||||
| async function createThread(members) { | ||||
|   const perms = document.querySelector( | ||||
|     'input[name="permissions"]:checked' | ||||
|   ).value; | ||||
|   let permissions; | ||||
|   let newmembers = members; | ||||
|   if (perms === "public") { | ||||
|     permissions = { | ||||
|       view_limited: false, | ||||
|       post_limited: false, | ||||
|     }; | ||||
|   } else if (perms === "private_post") { | ||||
|     permissions = { | ||||
|       view_limited: false, | ||||
|       post_limited: true, | ||||
|     }; | ||||
|   } else if (perms === "private_view") { | ||||
|     permissions = { | ||||
|       view_limited: true, | ||||
|       post_limited: true, | ||||
|     }; | ||||
|     // generate key
 | ||||
|     /* wip | ||||
|     var buf = new Uint8Array(32); | ||||
|     crypto.getRandomValues(buf); | ||||
|     const key = aesjs.utils.hex.fromBytes(Array.from(buf)); | ||||
|     // sign it to each of the members
 | ||||
|     for (let i = 0; i < newmembers.length; i++) { | ||||
|       const member = newmembers[i]; | ||||
|       const sig = await openpgp.encrypt({ | ||||
|         message: await openpgp.createMessage({ text: key }), | ||||
|         signingKeys: window.keys.priv, | ||||
|       }); | ||||
|     } | ||||
|     */ | ||||
|   } | ||||
|   window.socket.emit("create_thread", { | ||||
|     name: document.getElementById("newthreadname").value, | ||||
|     permissions, | ||||
|     newmembers, | ||||
|   }); | ||||
|   document.getElementById(perms).checked = false; | ||||
|   window.threadmembers = null; | ||||
|   document.getElementById("memberlist").innerHTML = ""; | ||||
|   const member = document.createElement("p"); | ||||
|   member.textContent = window.name; | ||||
|   member.classList.add("member"); | ||||
|   document.getElementById("memberlist").appendChild(member); | ||||
| 	const perms = document.querySelector( | ||||
| 		'input[name="permissions"]:checked' | ||||
| 	).value; | ||||
| 	let permissions; | ||||
| 	let newmembers = members; | ||||
| 	if (perms === "public") { | ||||
| 		permissions = { | ||||
| 			view_limited: false, | ||||
| 			post_limited: false, | ||||
| 		}; | ||||
| 	} else if (perms === "private_post") { | ||||
| 		permissions = { | ||||
| 			view_limited: false, | ||||
| 			post_limited: true, | ||||
| 		}; | ||||
| 	} else if (perms === "private_view") { | ||||
| 		permissions = { | ||||
| 			view_limited: true, | ||||
| 			post_limited: true, | ||||
| 		}; | ||||
| 		// generate key
 | ||||
| 		/* wip | ||||
| 		var buf = new Uint8Array(32); | ||||
| 		crypto.getRandomValues(buf); | ||||
| 		const key = aesjs.utils.hex.fromBytes(Array.from(buf)); | ||||
| 		// sign it to each of the members
 | ||||
| 		for (let i = 0; i < newmembers.length; i++) { | ||||
| 			const member = newmembers[i]; | ||||
| 			const sig = await openpgp.encrypt({ | ||||
| 				message: await openpgp.createMessage({ text: key }), | ||||
| 				signingKeys: window.keys.priv, | ||||
| 			}); | ||||
| 		} | ||||
| 		*/ | ||||
| 	} | ||||
| 	window.socket.emit("create_thread", { | ||||
| 		name: document.getElementById("newthreadname").value, | ||||
| 		permissions, | ||||
| 		newmembers, | ||||
| 	}); | ||||
| 	document.getElementById(perms).checked = false; | ||||
| 	window.threadmembers = null; | ||||
| 	document.getElementById("memberlist").innerHTML = ""; | ||||
| 	const member = document.createElement("p"); | ||||
| 	member.textContent = window.name; | ||||
| 	member.classList.add("member"); | ||||
| 	document.getElementById("memberlist").appendChild(member); | ||||
| } | ||||
| 
 | ||||
| function decryptMessage(thread, message) {} | ||||
|  | @ -129,126 +128,130 @@ function decryptMessage(thread, message) {} | |||
| function encryptMessage(thread, message) {} | ||||
| 
 | ||||
| window.onload = () => { | ||||
|   window.currentThreadId = 1; | ||||
|   window.socket = io(); | ||||
|   window.socket.on("create_user", auth); | ||||
|   window.socket.on("new_message", (msg) => { | ||||
|     if (msg.thread !== window.currentThreadId) return; | ||||
|     const el = document.createElement("div"); | ||||
|     el.classList.add("message"); | ||||
|     const strong = document.createElement("strong"); | ||||
|     strong.textContent = msg.name + ": "; | ||||
|     el.append(strong, msg.message); | ||||
|     document.getElementById("messages").appendChild(el); | ||||
|     if (!window.earliestMessage) window.earliestMessage = msg.id; | ||||
|   }); | ||||
|   window.socket.on("get_history", (msg) => { | ||||
|     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"); | ||||
|         const strong = document.createElement("strong"); | ||||
|         strong.textContent = message.name + ": "; | ||||
|         el.append(strong, message.message); | ||||
|         document.getElementById("messages").prepend(el); | ||||
|       } | ||||
|     } | ||||
|     if (!msg.more) document.getElementById("loadmore").classList.add("hidden"); | ||||
|   }); | ||||
|   window.socket.on("authenticate", (msg) => { | ||||
|     if (msg.success) { | ||||
|       document.getElementById("register").classList.add("hidden"); | ||||
|       document.getElementById("threads").classList.remove("hidden"); | ||||
|       document.getElementById("chat").classList.remove("hidden"); | ||||
|       const member = document.createElement("p"); | ||||
|       member.textContent = window.name; | ||||
|       member.classList.add("member"); | ||||
|       document.getElementById("memberlist").appendChild(member); | ||||
|       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); | ||||
|       }; | ||||
|       window.socket.emit("list_threads", {}); | ||||
|     } else { | ||||
|       document.getElementById("register").classList.remove("hidden"); | ||||
|     } | ||||
|   }); | ||||
|   window.socket.on("list_threads", (msg) => { | ||||
|     document.getElementById("threadlist").innerHTML = ""; | ||||
|     for (let thread of msg.threads) addThread(thread); | ||||
|   }); | ||||
|   window.socket.on("new_thread", addThread); | ||||
|   window.socket.on("create_thread", (msg) => { | ||||
|     chooseThread({ | ||||
|       name: document.getElementById("newthreadname").value, | ||||
|       id: msg.id, | ||||
|     }); | ||||
|     document.getElementById("newthreadname").value = ""; | ||||
|     document.getElementById("loadmore").classList.add("hidden"); | ||||
|     document.getElementById("msginput").classList.remove("hidden"); | ||||
|   }); | ||||
|   window.socket.on("get_keys", (msg) => { | ||||
|     createThread(msg.keys); | ||||
|   }); | ||||
|   document.getElementById("registerform").onsubmit = async (e) => { | ||||
|     e.preventDefault(); | ||||
|     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 }); | ||||
|   }; | ||||
|   document.getElementById("msginput").onsubmit = (e) => { | ||||
|     e.preventDefault(); | ||||
|     const msg = document.getElementById("msg").value; | ||||
|     if (!msg) return; | ||||
|     window.socket.emit("send_message", { | ||||
|       message: msg, | ||||
|       thread: window.currentThreadId, | ||||
|     }); | ||||
|     document.getElementById("msg").value = ""; | ||||
|   }; | ||||
|   document.getElementById("loadmore").onclick = (e) => { | ||||
|     loadMessages(); | ||||
|   }; | ||||
|   document.getElementById("createthread").onsubmit = (e) => { | ||||
|     e.preventDefault(); | ||||
|     const members = window.threadmembers | ||||
|       ? window.threadmembers.map((i) => ({ name: i })) | ||||
|       : [{ name: window.name }]; | ||||
|     const perms = document.querySelector( | ||||
|       'input[name="permissions"]:checked' | ||||
|     ).value; | ||||
|     console.log(perms, members); | ||||
|     if (perms === "private_view") { | ||||
|       window.socket.emit("get_keys", { names: members.map((i) => i.name) }); | ||||
|     } else { | ||||
|       createThread(members); | ||||
|     } | ||||
|   }; | ||||
|   document.getElementById("membername").onkeydown = (e) => { | ||||
|     if (e.key == "Enter") { | ||||
|       addMember(); | ||||
|     } | ||||
|   }; | ||||
|   document.getElementById("addmember").onclick = addMember; | ||||
| 	window.currentThreadId = 1; | ||||
| 	window.socket = io(); | ||||
| 	window.socket.on("create_user", auth); | ||||
| 	window.socket.on("new_message", (msg) => { | ||||
| 		if (msg.thread !== window.currentThreadId) return; | ||||
| 		const el = document.createElement("div"); | ||||
| 		el.classList.add("message"); | ||||
| 		const strong = document.createElement("strong"); | ||||
| 		strong.textContent = msg.name + ": "; | ||||
| 		el.append(strong, msg.message); | ||||
| 		document.getElementById("messages").appendChild(el); | ||||
| 		if (!window.earliestMessage) window.earliestMessage = msg.id; | ||||
| 	}); | ||||
| 	window.socket.on("get_history", (msg) => { | ||||
| 		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"); | ||||
| 				const strong = document.createElement("strong"); | ||||
| 				strong.textContent = message.name + ": "; | ||||
| 				el.append(strong, message.message); | ||||
| 				document.getElementById("messages").prepend(el); | ||||
| 			} | ||||
| 		} | ||||
| 		if (!msg.more) | ||||
| 			document.getElementById("loadmore").classList.add("hidden"); | ||||
| 		else | ||||
| 			document.getElementById("loadmore").classList.remove("hidden"); | ||||
| 	}); | ||||
| 	window.socket.on("authenticate", (msg) => { | ||||
| 		if (msg.success) { | ||||
| 			document.getElementById("register").classList.add("hidden"); | ||||
| 			document.getElementById("threads").classList.remove("hidden"); | ||||
| 			document.getElementById("chat").classList.remove("hidden"); | ||||
| 			const member = document.createElement("p"); | ||||
| 			member.textContent = window.name; | ||||
| 			member.classList.add("member"); | ||||
| 			document.getElementById("memberlist").appendChild(member); | ||||
| 			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); | ||||
| 			}; | ||||
| 			window.socket.emit("list_threads", {}); | ||||
| 			loadMessages(); | ||||
| 		} else { | ||||
| 			document.getElementById("register").classList.remove("hidden"); | ||||
| 		} | ||||
| 	}); | ||||
| 	window.socket.on("list_threads", (msg) => { | ||||
| 		document.getElementById("threadlist").innerHTML = ""; | ||||
| 		for (let thread of msg.threads) addThread(thread); | ||||
| 	}); | ||||
| 	window.socket.on("new_thread", addThread); | ||||
| 	window.socket.on("create_thread", (msg) => { | ||||
| 		chooseThread({ | ||||
| 			name: document.getElementById("newthreadname").value, | ||||
| 			id: msg.id, | ||||
| 		}); | ||||
| 		document.getElementById("newthreadname").value = ""; | ||||
| 		document.getElementById("loadmore").classList.add("hidden"); | ||||
| 		document.getElementById("msginput").classList.remove("hidden"); | ||||
| 	}); | ||||
| 	window.socket.on("get_keys", (msg) => { | ||||
| 		createThread(msg.keys); | ||||
| 	}); | ||||
| 	document.getElementById("registerform").onsubmit = async (e) => { | ||||
| 		e.preventDefault(); | ||||
| 		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 }); | ||||
| 	}; | ||||
| 	document.getElementById("msginput").onsubmit = (e) => { | ||||
| 		e.preventDefault(); | ||||
| 		const msg = document.getElementById("msg").value; | ||||
| 		if (!msg) return; | ||||
| 		window.socket.emit("send_message", { | ||||
| 			message: msg, | ||||
| 			thread: window.currentThreadId, | ||||
| 		}); | ||||
| 		document.getElementById("msg").value = ""; | ||||
| 	}; | ||||
| 	document.getElementById("loadmore").onclick = (e) => { | ||||
| 		loadMessages(); | ||||
| 	}; | ||||
| 	document.getElementById("createthread").onsubmit = (e) => { | ||||
| 		e.preventDefault(); | ||||
| 		const members = window.threadmembers | ||||
| 			? window.threadmembers.map((i) => ({ name: i })) | ||||
| 			: [{ name: window.name }]; | ||||
| 		const perms = document.querySelector( | ||||
| 			'input[name="permissions"]:checked' | ||||
| 		).value; | ||||
| 		console.log(perms, members); | ||||
| 		if (perms === "private_view") { | ||||
| 			window.socket.emit("get_keys", { names: members.map((i) => i.name) }); | ||||
| 		} else { | ||||
| 			createThread(members); | ||||
| 		} | ||||
| 	}; | ||||
| 	document.getElementById("membername").onkeydown = (e) => { | ||||
| 		if (e.key == "Enter") { | ||||
| 			addMember(); | ||||
| 		} | ||||
| 	}; | ||||
| 	document.getElementById("addmember").onclick = addMember; | ||||
| 
 | ||||
|   const keys = localStorage.getItem("keys"); | ||||
|   if (keys) { | ||||
|     window.name = localStorage.getItem("name"); | ||||
|     loadKeys(JSON.parse(keys)).then(() => {}); | ||||
|   } else document.getElementById("register").classList.remove("hidden"); | ||||
| 	const keys = localStorage.getItem("keys"); | ||||
| 	if (keys) { | ||||
| 		window.name = localStorage.getItem("name"); | ||||
| 		loadKeys(JSON.parse(keys)).then(() => {}); | ||||
| 	} else document.getElementById("register").classList.remove("hidden"); | ||||
| }; | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue