402 lines
9.9 KiB
JavaScript
Raw Normal View History

2025-01-18 13:21:38 +01:00
2025-01-26 22:48:58 +01:00
/*class Message {
2025-01-18 13:21:38 +01:00
uid = null
author = null
avatar = null
text = null
time = null
constructor(uid,avatar,author,text,time){
this.uid = uid
this.avatar = avatar
this.author = author
this.text = text
this.time = time
}
get links() {
if(!this.text)
return []
let result = []
for(let part in this.text.split(/[,; ]/)){
if(part.startsWith("http") || part.startsWith("www.") || part.indexOf(".com") || part.indexOf(".net") || part.indexOf(".io") || part.indexOf(".nl")){
result.push(part)
}
}
return result
}
get mentions() {
if(!this.text)
return []
let result = []
for(let part in this.text.split(/[,; ]/)){
if(part.startsWith("@")){
result.push(part)
}
}
return result
}
2025-01-26 22:48:58 +01:00
}*/
2025-01-18 13:21:38 +01:00
class Messages {
}
class Room {
2025-01-28 17:24:10 +01:00
name = null
2025-01-18 13:21:38 +01:00
messages = []
2025-01-28 17:24:10 +01:00
constructor(name) {
this.name = name
2025-01-18 13:21:38 +01:00
}
2025-01-28 17:24:10 +01:00
setMessages(list) {
2025-01-24 03:28:43 +01:00
2025-01-18 13:21:38 +01:00
}
}
2025-01-24 03:28:43 +01:00
class InlineAppElement extends HTMLElement {
2025-01-28 17:24:10 +01:00
constructor() {
// this.
2025-01-24 03:28:43 +01:00
}
}
class Page {
elements = []
}
2025-01-25 03:46:33 +01:00
class RESTClient {
2025-01-28 17:24:10 +01:00
debug = false
async get(url, params) {
params = params ? params : {}
2025-01-25 03:46:33 +01:00
const encodedParams = new URLSearchParams(params);
2025-01-28 17:24:10 +01:00
if (encodedParams)
2025-01-25 03:46:33 +01:00
url += '?' + encodedParams
2025-01-28 17:24:10 +01:00
const response = await fetch(url, {
2025-01-25 03:46:33 +01:00
method: 'GET',
headers: {
2025-01-28 17:24:10 +01:00
'Content-Type': 'application/json'
2025-01-25 03:46:33 +01:00
}
2025-01-28 17:24:10 +01:00
});
const result = await response.json()
if (this.debug) {
console.debug({ url: url, params: params, result: result })
}
return result
2025-01-25 03:46:33 +01:00
}
async post(url, data) {
2025-01-28 17:24:10 +01:00
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json()
if (this.debug) {
console.debug({ url: url, params: params, result: result })
}
2025-01-25 03:46:33 +01:00
return result
}
}
const rest = new RESTClient()
2025-01-25 05:50:23 +01:00
class EventHandler {
2025-01-28 17:24:10 +01:00
constructor() {
2025-01-25 05:50:23 +01:00
this.subscribers = {}
}
2025-01-28 17:24:10 +01:00
addEventListener(type, handler) {
if (!this.subscribers[type])
2025-01-25 05:50:23 +01:00
this.subscribers[type] = []
this.subscribers[type].push(handler)
}
2025-01-28 17:24:10 +01:00
emit(type, ...data) {
if (this.subscribers[type])
this.subscribers[type].forEach(handler => handler(...data))
2025-01-25 05:50:23 +01:00
}
}
class Chat extends EventHandler {
constructor() {
super()
2025-01-28 17:24:10 +01:00
this._url = window.location.hostname == 'localhost' ? 'ws://localhost/chat.ws' : 'wss://' + window.location.hostname + '/chat.ws'
this._socket = null
this._wait_connect = null
2025-01-25 05:50:23 +01:00
this._promises = {}
}
2025-01-28 17:24:10 +01:00
connect() {
if (this._wait_connect)
2025-01-25 05:50:23 +01:00
return this._wait_connect
2025-01-28 17:24:10 +01:00
const me = this
return new Promise(async (resolve, reject) => {
me._wait_connect = resolve
console.debug("Connecting..")
2025-01-28 20:41:24 +01:00
try {
me._socket = new WebSocket(me._url)
}catch(e){
console.warning(e)
setTimeout(()=>{
me.ensureConnection()
},1000)
}
2025-01-28 17:24:10 +01:00
me._socket.onconnect = () => {
me._connected()
me._wait_socket(me)
}
})
2025-01-25 05:50:23 +01:00
}
generateUniqueId() {
return 'id-' + Math.random().toString(36).substr(2, 9); // Example: id-k5f9zq7
}
2025-01-28 17:24:10 +01:00
call(method, ...args) {
const me = this
return new Promise(async (resolve, reject) => {
try {
const command = { method: method, args: args, message_id: me.generateUniqueId() }
2025-01-25 05:50:23 +01:00
me._promises[command.message_id] = resolve
2025-01-28 17:24:10 +01:00
await me._socket.send(JSON.stringify(command))
} catch (e) {
2025-01-25 05:50:23 +01:00
reject(e)
}
})
}
_connected() {
2025-01-28 17:24:10 +01:00
const me = this
2025-01-25 05:50:23 +01:00
this._socket.onmessage = (event) => {
const message = JSON.parse(event.data)
2025-01-28 17:24:10 +01:00
if (message.message_id && me._promises[message.message_id]) {
2025-01-25 05:50:23 +01:00
me._promises[message.message_id](message)
delete me._promises[message.message_id]
2025-01-28 17:24:10 +01:00
} else {
me.emit("message", me, message)
2025-01-25 05:50:23 +01:00
}
//const room = this.rooms.find(room=>room.name == message.room)
//if(!room){
2025-01-28 17:24:10 +01:00
// this.rooms.push(new Room(message.room))
2025-01-25 05:50:23 +01:00
}
this._socket.onclose = (event) => {
2025-01-28 17:24:10 +01:00
me._wait_socket = null
me._socket = null
me.emit('close', me)
2025-01-25 05:50:23 +01:00
}
}
async privmsg(room, text) {
2025-01-28 17:24:10 +01:00
await rest.post("/api/privmsg", {
room: room,
text: text
2025-01-25 05:50:23 +01:00
})
}
}
2025-01-26 22:48:58 +01:00
class Socket extends EventHandler {
2025-01-28 17:24:10 +01:00
ws = null
2025-01-26 22:48:58 +01:00
isConnected = null
isConnecting = null
2025-01-26 22:54:29 +01:00
url = null
2025-01-26 22:48:58 +01:00
connectPromises = []
2025-01-28 20:41:24 +01:00
ensureTimer = null
2025-01-26 22:48:58 +01:00
constructor() {
super()
2025-01-28 17:24:10 +01:00
this.url = window.location.hostname == 'localhost' ? 'ws://localhost:8081/rpc.ws' : 'wss://' + window.location.hostname + '/rpc.ws'
this.ensureConnection()
2025-01-26 22:48:58 +01:00
}
_camelToSnake(str) {
return str
2025-01-28 17:24:10 +01:00
.replace(/([a-z])([A-Z])/g, '$1_$2')
.toLowerCase();
2025-01-26 22:48:58 +01:00
}
get client() {
const me = this
const proxy = new Proxy(
{},
{
2025-01-28 17:24:10 +01:00
get(target, prop) {
return (...args) => {
let functionName = me._camelToSnake(prop)
return me.call(functionName, ...args);
};
},
2025-01-26 22:48:58 +01:00
}
2025-01-28 17:24:10 +01:00
);
2025-01-26 22:48:58 +01:00
return proxy
}
2025-01-28 17:24:10 +01:00
ensureConnection() {
2025-01-28 20:41:24 +01:00
if(this.ensureTimer)
return this.connect()
const me = this
this.ensureTimer = setInterval(()=>{
if (me.isConnecting)
me.isConnecting = false
me.connect()
},5000)
2025-01-26 22:48:58 +01:00
return this.connect()
}
generateUniqueId() {
2025-01-28 17:24:10 +01:00
return 'id-' + Math.random().toString(36).substr(2, 9);
2025-01-26 22:48:58 +01:00
}
2025-01-28 17:24:10 +01:00
connect() {
const me = this
if (!this.isConnected && !this.isConnecting) {
this.isConnecting = true
} else if (this.isConnecting) {
return new Promise((resolve, reject) => {
2025-01-26 22:48:58 +01:00
me.connectPromises.push(resolve)
2025-01-28 17:24:10 +01:00
})
} else if (this.isConnected) {
return new Promise((resolve, reject) => {
2025-01-26 22:48:58 +01:00
resolve(me)
})
}
2025-01-28 17:24:10 +01:00
return new Promise((resolve, reject) => {
2025-01-26 22:48:58 +01:00
me.connectPromises.push(resolve)
2025-01-28 20:41:24 +01:00
console.debug("Connecting..")
2025-01-26 22:54:29 +01:00
const ws = new WebSocket(this.url)
2025-01-28 20:41:24 +01:00
ws.onopen = (event) => {
2025-01-28 17:24:10 +01:00
me.ws = ws
me.isConnected = true
2025-01-26 22:48:58 +01:00
me.isConnecting = false
ws.onmessage = (event) => {
me.onData(JSON.parse(event.data))
}
2025-01-28 17:24:10 +01:00
ws.onclose = (event) => {
2025-01-26 22:48:58 +01:00
me.onClose()
2025-01-28 17:24:10 +01:00
2025-01-26 22:48:58 +01:00
}
2025-01-28 20:41:24 +01:00
ws.onerror = (event)=>{
me.onClose()
}
2025-01-28 17:24:10 +01:00
me.connectPromises.forEach(resolve => {
resolve(me)
2025-01-26 22:48:58 +01:00
})
}
})
}
2025-01-28 17:24:10 +01:00
onData(data) {
2025-01-29 06:43:42 +01:00
if(data.success != undefined && !data.success){
console.error(data)
}
2025-01-28 17:24:10 +01:00
if (data.callId) {
2025-01-26 22:48:58 +01:00
this.emit(data.callId, data.data)
}
2025-01-28 17:24:10 +01:00
if (data.channel_uid) {
this.emit(data.channel_uid, data.data)
this.emit("channel-message", data)
2025-01-26 22:48:58 +01:00
}
2025-01-28 17:24:10 +01:00
2025-01-26 22:48:58 +01:00
}
2025-01-28 17:24:10 +01:00
async sendJson(data) {
return await this.connect().then((api) => {
2025-01-26 22:48:58 +01:00
api.ws.send(JSON.stringify(data))
})
}
2025-01-28 20:41:24 +01:00
2025-01-28 17:24:10 +01:00
async call(method, ...args) {
const call = {
2025-01-26 22:48:58 +01:00
callId: this.generateUniqueId(),
method: method,
args: args
}
2025-01-28 17:24:10 +01:00
const me = this
return new Promise(async (resolve, reject) => {
me.addEventListener(call.callId, (data) => {
resolve(data)
2025-01-26 22:48:58 +01:00
})
2025-01-28 17:24:10 +01:00
await me.sendJson(call)
})
2025-01-26 22:48:58 +01:00
}
2025-01-28 17:24:10 +01:00
onClose() {
2025-01-26 22:48:58 +01:00
console.info("Connection lost. Reconnecting.")
2025-01-28 17:24:10 +01:00
this.isConnected = false
2025-01-26 22:48:58 +01:00
this.isConnecting = false
2025-01-28 17:24:10 +01:00
this.ensureConnection().then(() => {
2025-01-26 22:48:58 +01:00
console.info("Reconnected.")
})
}
}
2025-01-25 05:50:23 +01:00
2025-01-26 22:48:58 +01:00
class App extends EventHandler {
2025-01-18 13:21:38 +01:00
rooms = []
2025-01-28 17:24:10 +01:00
rest = rest
ws = null
rpc = null
sounds = ["/audio/soundfx.d_beep3.mp3"]
playSound(soundIndex) {
if (!soundIndex)
soundIndex = 0
const player = new Audio(this.sounds[soundIndex]);
player.play()
.then(() => {
console.debug("Gave sound notification")
})
.catch((error) => {
console.error("Notification failed:", error);
});
}
2025-01-18 13:21:38 +01:00
constructor() {
2025-01-26 22:48:58 +01:00
super()
2025-01-18 13:21:38 +01:00
this.rooms.push(new Room("General"))
2025-01-26 22:48:58 +01:00
this.ws = new Socket()
2025-01-28 17:24:10 +01:00
this.rpc = this.ws.client
const me = this
2025-01-26 22:48:58 +01:00
this.ws.addEventListener("channel-message", (data) => {
2025-01-28 17:24:10 +01:00
me.emit(data.channel_uid, data)
})
2025-01-18 13:21:38 +01:00
}
2025-01-28 17:24:10 +01:00
async benchMark(times, message) {
if (!times)
2025-01-26 22:48:58 +01:00
times = 100
2025-01-28 17:24:10 +01:00
if (!message)
2025-01-28 17:11:30 +01:00
message = "Benchmark Message"
2025-01-26 22:48:58 +01:00
let promises = []
2025-01-28 17:24:10 +01:00
const me = this
for (let i = 0; i < times; i++) {
promises.push(this.rpc.getChannels().then(channels => {
channels.forEach(channel => {
me.rpc.sendMessage(channel.uid, `${message} ${i}`).then(data => {
2025-01-26 22:48:58 +01:00
})
})
}))
2025-01-28 17:24:10 +01:00
2025-01-26 22:48:58 +01:00
}
2025-01-27 03:16:44 +01:00
//return await Promise.all(promises)
2025-01-28 17:24:10 +01:00
2025-01-25 03:46:33 +01:00
}
2025-01-18 13:21:38 +01:00
2025-01-26 22:48:58 +01:00
}
const app = new App()