socketify.py/examples/chat/assets/scripts.js

201 wiersze
5.6 KiB
JavaScript

function get_room(name, token, on_history, on_message){
const ws = new WebSocket(`ws://localhost:3000?room=${name}&token=${token}`);
var status = 'pending';
const connection = new Promise((resolve)=>{
ws.onopen = function(){
status = 'connected';
resolve(true)
}
ws.onerror = function(){
status = 'error';
resolve(false)
}
});
ws.onclose = function(){
status = 'closed';
}
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if(message instanceof Array){
on_history(message)
}else{
on_message(message)
}
}
return {
send(message){
ws.send(JSON.stringify(message));
},
wait_connection(){
return connection;
},
is_connected(){
return status === 'connected';
},
close(){
ws.close()
}
}
}
function get_utc_date(){
return new Date().toLocaleTimeString('en-US', { hour12:false, hour: '2-digit', minute: '2-digit', timeZone: 'UTC', timeZoneName: 'short' })
}
function get_session() {
let name = "session=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
async function get_user() {
const session = get_session()
if (!session) return null;
try {
const response = await fetch('https://api.github.com/user', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session}`,
'Accept': 'application/json'
}
})
return await response?.json()
} catch (err) {
console.error(err);
return null;
}
}
function request_login(){
return document.location.href = 'https://github.com/login/oauth/authorize?scope=user:email&client_id=9481803176fb73d616b7';
}
let current_room = null;
let last_room_name = 'general';
async function send_message(event){
if(event && event.key?.toLowerCase() !== 'enter') return;
const message = document.querySelector("#chat-message");
await current_room?.wait_connection();
if(current_room?.is_connected()){
current_room.send({
text: message.value,
datetime: get_utc_date()
})
//clean
message.value = ''
}else {
await open_room(last_room_name)
send_message();
}
}
async function open_room(name){
last_room_name = name;
current_room?.close()
const user = await get_user();
if(!user){
return request_login();
}
const chat = document.querySelector('.chat-messages');
const room = get_room(name, get_session(), (history)=> {
//clear
chat.innerHTML = '';
//add messages
for(let message of history){
chat.appendChild(format_message(message, user));
}
chat.scroll(0, chat.scrollHeight)
}, (message)=>{
//add message
chat.appendChild(format_message(message, user));
//trim size
while(chat.childNodes.length > 100){
chat.firstChild.remove();
}
chat.scroll(0, chat.scrollHeight)
});
await room.wait_connection()
current_room = room;
}
const markdown = new showdown.Converter({simpleLineBreaks: true,openLinksInNewWindow: true, emoji: true, ghMentions: true, tables: true, strikethrough: true, tasklists: true});
function format_message(message, user){
const message_element = document.createElement("div");
if(message.login === user.login){
message.name = 'You';
message_element.classList.add('chat-message-right');
}else{
message.name = message.name || message.login;
message_element.classList.add('chat-message-left');
}
message_element.classList.add('pb-4');
const header = document.createElement("div");
image = new Image(40, 40);
image.src = message.avatar_url;
image.classList.add('rounded-circle');
image.classList.add('mr-1');
image.alt = message.name;
const date = document.createElement("div");
date.classList.add('text-muted');
date.classList.add('small');
date.classList.add('text-nowrap');
date.classList.add('mt-2');
date.textContent = message.datetime;
header.addEventListener("click", ()=> {
window.open(message.html_url, '_blank').focus();
});
header.appendChild(image);
header.appendChild(date);
message_element.appendChild(header);
const body = document.createElement("div");
body.classList.add('flex-shrink-1');
body.classList.add('bg-light');
body.classList.add('rounded');
body.classList.add('py-2');
body.classList.add('px-3');
body.classList.add('mr-3');
const author = document.createElement("div")
author.classList.add('font-weight-bold');
author.classList.add('mb-1');
author.textContent = message.name;
body.appendChild(author);
const content = document.createElement("div");
content.innerHTML = markdown.makeHtml(message.text);
body.appendChild(content);
message_element.appendChild(body);
return message_element;
}
get_user().then((is_logged_in)=>{
if(is_logged_in){
open_room("general");
}
});