import { SocketIOProvider } from '../providers/socketio'; import { RayconnectBase } from './base' import { emitDataWithError, emitDataWithTimeout } from './events'; import { Options, ExecuteType, QueryType, ServerData, QueryCallback, Permission, Service } from './types'; import { observable, Observable } from 'rxjs'; import { resolve } from 'path'; export class RayconnectSdk extends RayconnectBase { constructor(ops: Options, token: any, config: any) { super(ops, token, config, SocketIOProvider); } private requests: any = []; private response: Set = new Set(); private requestComplete: Observable = new Observable(); async connected() { return new Promise((resolve, reject) => { this.socket.once("connect", () => { clearTimeout(TIMEOUT); resolve(true); }); const TIMEOUT = setTimeout(() => { reject("connection timeout"); }, 30000); }); } async getPrivateAuthToken() { return new Promise((resolve) => { setTimeout(() => { resolve(this.privateAuthToken); }, 10); }) } async isAuth() { if (this.authed) { return Promise.resolve(true); } return new Promise((resolve, reject) => { this.socket.once("authed", () => { clearTimeout(TIMEOUT); resolve(true); }); const TIMEOUT = setTimeout(() => { reject("auth timeout"); }, 30000); }); } RequestOTP(phone: any, TimeOutNumber = 120000) { return emitDataWithTimeout(this.socket, { key: "login", response_key: "login", value: { phone }, }, true); } VerifyPhone(phone: any, token: any, TimeOutNumber = 120000) { this.socket.emit("login", { phone, token }); return new Promise((resolve, reject) => { const TimeOut = setTimeout(() => { reject(`request timeout : ${TimeOutNumber}`); }, TimeOutNumber); this.readData("login", (msg: any) => { const data = this.Dpack(msg); clearTimeout(TimeOut); resolve(data); }); }); } async GetPhoneAccess(phone: any, token: any) { try { if (this.user) { return this.user; } const verify: any = await this.VerifyPhone(phone, token, 30000); if (verify.status) { await this.getAccess(verify.data.token); return verify; } else { throw verify; } } catch (error) { throw error; } } setProfile(data: any, TimeOutNumber = 60000) { return emitDataWithTimeout(this.socket, { key: "profile", response_key: "profile_set", value: { method: "SET", data: data, }, }); } getProfile(data: any, TimeOutNumber = 60000) { return emitDataWithTimeout(this.socket, { key: "profile", response_key: "profile_get", value: { method: "GET", data: data, }, }); } async GetGuestAccess() { if (this.user) { return this.user; } const guest = await this.Guest(); return this.getAccess(guest["data"]["token"]); } async GetUserAccess( data = { username: "", password: "" }, TimeOutNumber = 30000, logout=false ) { if ((this.user) && (!logout)) { return this.user; } try { const user = await this.LoginWithPassword(data, TimeOutNumber); if (!user.status) return Promise.reject(user) return this.getAccess(user["data"]["token"]); } catch (error) { return Promise.reject(error) } } async GetUserAccessNB( data = { username: "", password: "" }, TimeOutNumber = 30000, ) { try { const user = await this.LoginWithPassword(data, TimeOutNumber); if (!user.status) return Promise.reject(user) return this.getAccess(user["data"]["token"]); } catch (error) { return Promise.reject(error) } } async Guest(TimeOutNumber = 30000) { if (!this.authed) { if (this.device?.type == 'browser') { const api = `https://s1.iranserver1.rayconnect.ir/api/v2/guest?aid=${this.ops.appID}` const result = await fetch(api); const response = { 'data': await result.json() } return response; } } return this.LoginWithPassword(); } LoginWithPassword( data = { username: "guest", password: "guest" }, TimeOutNumber = 30000 ): Promise { this.loginData = data; this.socket.emit("loginup", data); return new Promise((resolve, reject) => { const TimeOut = setTimeout(() => { reject(`request timeout : ${TimeOutNumber}`); }, TimeOutNumber); this.readData("login", (msg: any) => { const data = this.Dpack(msg); clearTimeout(TimeOut); resolve(data); }); }); } execQuery(param: ExecuteType, mid?: any, TimeOutNumber = 30000) { const self = this; try { return new Promise((resolve, reject) => { const TimeOut = setTimeout(() => { reject(`request timeout : ${TimeOutNumber}`); }, TimeOutNumber); if (mid) { param.info.msg_id = mid; } else { param.info.msg_id = self.getMessageID(); } param.info.data = JSON.stringify(param.info.data); self.socket.emit("exec_gram", param); self.readData( `exec_gram_response_${param.info.msg_id}`, async (msg: any) => { // send ack const objectData = msg; // callback clearTimeout(TimeOut); if (objectData.type == "ok") { resolve(objectData); } else { reject(objectData); } } ); }); } catch (error) { } } Request(execObj: ExecuteType, queryObj: QueryType, TimeOutNumber = 30000) { return new Promise((resolve, reject) => { const TimeOut = setTimeout(() => { reject(`request timeout : ${TimeOutNumber}`); }, TimeOutNumber); this.execQuery(execObj); this.readData("blocked", () => { reject(`blocked `); clearTimeout(TimeOut); }); this.readData(`exec_gram_${queryObj.address}`, async (msg: any) => { this.services.query.executeMiddleware ( this.middlewares, { query: queryObj, exec: execObj, msg: msg, }, (info: any, next: any) => { try { const data = this.Dpack(msg); if ( data.scope === queryObj.scope && data.address === queryObj.address && data.info.method === queryObj.method ) { // send ack this.Ack(data.info.reqID); const objectData = JSON.parse(data.info.data); // callback clearTimeout(TimeOut); const send = (sendData: any, token?: any) => { let address = queryObj.address + "/back"; if (data.info.msg_id) { address = address + "/" + data.info.msg_id; } if (data.info.gateway_id) { token = true data.token = data.info.gateway_id } this.execQuery({ scope: queryObj.scope, uniqueID: token ? "*" : data.sender, TokenID: token ? data.token : "*", address: address, info: { method: queryObj.method, data: sendData, }, }); }; const resolvedata: ServerData = { sender: data.uid, token: data.token, data: objectData, date: data.info.date, send: send, }; resolve(resolvedata); } } catch (error) { reject(error); } } ); }); }); } protected async getFromNimkatApi(type: string, id?: string, action = "findall") { switch (action) { case "findall": const api = `https://s1.iranserver1.rayconnect.ir/api/v2/nimkat/${type}?aid=${this.ops.appID}&token=${await this.getPrivateAuthToken()}&noPermission=true` return fetch(api) } } async loadProfile() { const api = `https://s1.iranserver1.rayconnect.ir/api/v2/me?aid=${this.ops.appID}&token=${await this.getPrivateAuthToken()}` const result = await fetch(api); const me_user = await result.json(); this.user = me_user } async RequestBack(execObj: ExecuteType, TimeOutNumber = 30000) { const m_id = this.getMessageID(); // make query object from exec const queryObj: QueryType = { scope: execObj.scope, address: execObj.address + "/back/" + m_id, method: execObj.info.method, }; if (!this.authed) { if (this.device?.type == 'browser') { const rawResponse = await fetch(`https://http-gateway.ir/api/v1/run/?token=${await this.getPrivateAuthToken()}&aid=${this.ops.appID}`, { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "address": execObj.address, "method": execObj.info.method, "scope": execObj.scope, "data": execObj.info.data, "user": execObj.uniqueID, "token": execObj.TokenID }) }); return Promise.resolve(rawResponse.json()); } } return new Promise(async (resolve, reject) => { const TimeOut = setTimeout(() => { reject(`request timeout : ${TimeOutNumber}`); }, TimeOutNumber); /*this.readData("blocked", () => { reject(`blocked `); clearTimeout(TimeOut); });*/ try { await this.execQuery(execObj, m_id); } catch (error) { reject(error) } this.readData(`exec_gram_${queryObj.address}`, async (msg: any) => { this.services.query.executeMiddleware ( this.middlewares, { query: queryObj, exec: execObj, msg: msg, }, (info: any, next: any) => { try { const data = this.Dpack(msg); if ( data.scope === queryObj.scope && data.address === queryObj.address && data.info.method === queryObj.method ) { // send ack this.Ack(data.info.reqID); const objectData = JSON.parse(data.info.data); // callback clearTimeout(TimeOut); const send = (sendData: any, token?: any) => { let address = queryObj.address + "/back"; if (data.info.msg_id) { address = address + "/" + data.info.msg_id; } if (data.info.gateway_id) { token = true data.token = data.info.gateway_id } this.execQuery({ scope: queryObj.scope, uniqueID: token ? "*" : data.sender, TokenID: token ? data.token : "*", address: address, info: { method: queryObj.method, data: sendData, }, }); }; if (execObj.uniqueID != "*") { if (data.uid != execObj.uniqueID) { console.log("woman in the royal room !"); reject("woman in the royal room !"); return } } if (execObj.uniqueID == "guest") { reject("Guest user cannot be a server"); return } if (execObj.TokenID != "*") { if (data.token != execObj.TokenID) { console.log("woman in the royal room ! (token)"); reject("woman in the royal room ! (token)"); return } } const resolvedata: ServerData = { sender: data.uid || data.token, token: data.token, data: objectData, date: data.info.date, send: send, }; resolve(resolvedata); } } catch (error) { console.log(error) reject(error); } } ); }); }); } IsQuery(input: ExecuteType, query: QueryType) { return ( input.scope === query.scope && input.address === query.address && input.info.method === query.method ); } Query(queryObj: QueryType, callback: QueryCallback) { this.socket.on( `exec_gram_${queryObj.address}`, async (msg: any, ack: any) => { try { const data = msg; if ( this.IsQuery(data, queryObj) ) { // send ack this.Ack(data.info.reqID) const objectData = JSON.parse(data.info.data); // callback const send = (sendData: any, token?: any, cache?: { ttl: number, update?: boolean, delete?: boolean }) => { let address = queryObj.address + "/back"; if (data.info.msg_id) { address = address + "/" + data.info.msg_id; } if (data.info.gateway_id) { token = true data.token = data.info.gateway_id } this.execQuery({ scope: queryObj.scope, uniqueID: token ? "*" : data.uid, TokenID: token ? data.token : "*", address: address, info: { method: queryObj.method, response: true, data: sendData, cache: cache ? cache : undefined }, }); }; const body = this.requestDataConvertor(objectData); this.services.query.executeMiddleware ( this.middlewares, { query: queryObj, msg: msg, send: send, }, (info: any, next: any) => { callback( { sender: data.uid, token: data.token, data: objectData, body: body, date: data.info.date, send: send, }, queryObj ); } ); // callback } } catch (error) { } } ); } News(callback: (arg0: any) => void) { this.socket.on("news", async (msg: any) => { this.Dpack(msg); const data = this.Dpack(msg); callback(data); }); } addUser(param: { username: string, password: string }) { return emitDataWithTimeout(this.socket, { key: "add_user", response_key: "added_user", value: param, }); } RegisterUser(param: { email: string, password: string, phone?: string }) { console.log("running emit") return emitDataWithTimeout(this.socket, { key: "register_email", response_key: "registered_email", value: { username: param.email, password: param.password, phone: param.phone }, }); } findABI() { return emitDataWithTimeout(this.socket, { key: "abi_find", response_key: "abi_finded", value: { }, }); } requestDataConvertor(request: any) { let data = {}; if (typeof request.data !== "object") { return {}; } else { data = { ...data, ...request.data }; } if (request.data.query) { data = { ...data, ...request.data.query }; } if (request.data.data) { data = { ...data, ...request.data.data }; } return data; } changePermissions(param: Permission) { return emitDataWithTimeout(this.socket, { key: "change_permissions", response_key: "changed_permission", value: param, }); } // TODO loadService(param: Service[]) { return emitDataWithTimeout(this.socket, { key: "load_service", response_key: "loaded_service", value: param, }); } checkAuth(token: string, aid: string) { return emitDataWithTimeout(this.socket, { key: "check_auth", response_key: "auth_checked", value: { token, aid }, }, true); } // TODO getVAPIDPublicKey() { return emitDataWithTimeout(this.socket, { key: "get_vapid_publickey", response_key: "got_vapid_publickey", value: null, }, true); } // TODO sendNotificationRegisteration(param: any) { return emitDataWithTimeout(this.socket, { key: "send_notification_register", response_key: "received_notification_register", value: param, }); } // TODO channel(param: string) { return emitDataWithTimeout(this.socket, { key: "join_channel", response_key: "joined_channel", value: param, }); } updatePassword(param: any) { return emitDataWithTimeout(this.socket, { key: "update_password", response_key: "updated_password", value: param, }); } public upload(name: string = "file.file") { } public download(name: string = "file.file") { } async newApp(data: any) { if (data.aid) { return emitDataWithError(this.socket, { key: "apps", response_key: "apps_create", error_key: "apps_error", value: { method: "create", data: data, }, }); } } use(fn: Function) { this.middlewares.push(fn); } close() { this.socket.disconnect(); } }