import { Injectable } from '@angular/core'; import { v4 as uuidv4 } from 'uuid' import { wsCallbacksParams, msgQueue } from 'src/app/models/rochet-chat-cliente-service' import { deepFind } from 'src/plugin/deep' import { environment } from 'src/environments/environment'; /** * Use this class to interact with rocketChat realtime API */ @Injectable({ providedIn: 'root' }) export class RocketChatClientService { private firstPingFunx: Function isLogin = false; constructor() {} connect(firstPingFunx: Function) { this.firstPingFunx = firstPingFunx // this.ws.connect(environment.apiWsChatUrl); const connectMessage = { msg: "connect", version: "1", support: ["1"] } this.ws.send(connectMessage, 'connect', false) this.ws.send({msg:"pong"},'recoonect', false) firstPingFunx() } login(user) { const requestId = uuidv4() this.isLogin = false const loginRequest = { msg: "method", method: "login", id: requestId, params: [ { user: { username: user.username }, password: user.password } ] } this.ws.send(loginRequest, requestId, false) return new Promise((resolve, reject) => { this.ws.registerCallback({type:'Onmessage', requestId, funx:(message)=>{ if(message.id == requestId ) { // same request send if(message.result.token) { this.isLogin = true this.ws.wsMsgQueue() resolve(message) } else { this.isLogin = false reject(message) } reject(message) return true } }}) }); } getRooms(roomOlder = 1480377601) { const requestId = uuidv4() const request = { "msg": "method", "method": "rooms/get", "id": requestId, "params": [ { "$date": 1480377601 } ] } this.ws.send(request, requestId, true) return new Promise((resolve, reject) => { this.ws.registerCallback({type:'Onmessage', requestId, funx:(message)=>{ if(message.id == requestId) { // same request send resolve(message) return true } }}) }); } logout() {} send(roomId, message) { const requestId = uuidv4() var request = { msg: "method", method: "sendMessage", id: requestId, params: [{ _id: uuidv4(), rid: roomId, msg: message }] } this.ws.send(request, requestId, true); return new Promise((resolve, reject) => { this.ws.registerCallback({type:'Onmessage', requestId, funx:(message)=>{ if(message.id == requestId || deepFind(message,'result.id') == requestId) { // same request send resolve(message) return true } }}) }); } joinRoom(){} deleteMessage() {} createRoom() {} loadHistory(roomId, limit: number = 50) { const requestId = uuidv4() const request = { msg: "method", method: "loadHistory", id: requestId, params: [ roomId, null, limit, { "$date": 1480377601 } ] } this.ws.send(request, requestId, true) return new Promise((resolve, reject) => { this.ws.registerCallback({type:'Onmessage', requestId, funx:(message)=>{ // console.log(message) if(message.id == requestId ) { // same request send resolve(message) return true } }}) }); } subscribe(roomId : string) { const requestId = uuidv4() var subscribeRequest = { "msg": "sub", "id": requestId, "name": "stream-notify-room", "params":[ `${roomId}/event`, false ] } this.ws.send(subscribeRequest, requestId, true); return new Promise((resolve, reject) => { this.ws.registerCallback({type:'Onmessage', requestId, funx:(message)=>{ if(message.msg == 'ready' || deepFind(message, 'subs.0') == requestId) { // same request send resolve(message) return true } }}) }); } /** * @param roomId * @param key * @param funx */ receiveLiveMessageFromRoom(roomId =')(', key, funx: Function) { this.ws.registerCallback({ type:'Onmessage', requestId: key, funx:(message)=>{ if(message.msg =='result') { if(message.result.msg) { if(message.result.rid == roomId) { funx(message) } } } } }) } streamRoomMessages(roomId : string) { const requestId = uuidv4() const request = { "msg": "sub", "id": requestId, "name": "stream-room-messages", "params":[ `${roomId}/event`, false ] } this.ws.send(request, requestId, true); return new Promise((resolve, reject) => { this.ws.registerCallback({type:'Onmessage', requestId, funx:(message)=>{ if(message.msg == 'ready' || deepFind(message, 'subs.0') == requestId) { // same request send resolve(message) return true } }}) }); } streamNotifyRoom(roomId : string) { const requestId = uuidv4() let streamNotifyObj = { "msg": "method", "method": "stream-notify-room", "id": requestId, "params": [ `null/typing`, "paulo.pinto", true ] }; this.ws.send(streamNotifyObj, requestId, true) return new Promise((resolve, reject) => { this.ws.registerCallback({type:'Onmessage', requestId, funx:(message)=>{ if(message.id == requestId || deepFind(message,'result.id') == requestId) { // same request send resolve('') return true } }}) }); } registerCallback(data:wsCallbacksParams) { return this.ws.registerCallback(data) } // socket class ================================================================== private socket!: WebSocket; private wsUrl = '' private wsMsgQueue : msgQueue[] = [] private wsCallbacks: {[key: string]: wsCallbacksParams} = {} private ws = { connected: false, registerCallback:(params: wsCallbacksParams) => { if(!params.requestId) { params.requestId = uuidv4() } this.wsCallbacks[params.requestId] = { type: params.type, funx: params.funx } }, connect:(url)=> { this.wsUrl = url this.socket = new WebSocket(this.wsUrl); // bind function this.socket.onopen = this.ws.onopen; this.socket.onmessage = this.ws.onmessage; this.socket.onclose = this.ws.onclose; this.socket.onerror = this.ws.onerror; }, onopen:()=> { this.ws.connected = true console.log('================== welcome to socket server =====================') this.ws.wsMsgQueue() }, wsMsgQueue:()=> { this.wsMsgQueue.forEach((item, index, object) => { if(item.loginRequired == true && this.isLogin == true) { console.log('run msgQueue ',index) this.ws.send(item.message, item.requestId, item.loginRequired); delete this.wsMsgQueue[item.requestId] } else if(item.loginRequired == false) { console.log('run msgQueue ',index) this.ws.send(item.message, item.requestId, item.loginRequired); delete this.wsMsgQueue[item.requestId] } }) }, send: (message: object, requestId = uuidv4(), loginRequired) => { if (this.ws.connected == false || loginRequired == true && this.isLogin == false) { // save data to send when back online console.log('save msgQueue this.ws.connected == false || loginRequired == true && this.isLogin == false',this.ws.connected, loginRequired, this.isLogin) this.wsMsgQueue.push({message, requestId, loginRequired}) } else { let messageStr = JSON.stringify(message) this.socket.send(messageStr) } return requestId }, onmessage:(event: any)=> { const data = JSON.parse(event.data) // console.log('event.data', data) for (const [key, value] of Object.entries(this.wsCallbacks)) { if(value.type== 'Onmessage') { const dontRepeat = value.funx(data) if(dontRepeat) { delete this.wsCallbacks[key] } } } }, onclose:(event: any)=> { this.connect(this.firstPingFunx()) this.ws.connected = false console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`); }, onerror: (event: any) => { console.log(`[error] ${event.message}`); } } }