DataTransfer Ended
This commit is contained in:
parent
ae3db888ca
commit
a4fdf12838
|
@ -16,6 +16,10 @@ function Client()
|
||||||
this.store = new Map();
|
this.store = new Map();
|
||||||
this.rooms = new Set();
|
this.rooms = new Set();
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* @type {Map<string, Client>}
|
||||||
|
*/
|
||||||
|
Client.clients = new Map();
|
||||||
|
|
||||||
Client.prototype.send = function(obj){
|
Client.prototype.send = function(obj){
|
||||||
this.socket.sendUTF(JSON.stringify(obj));
|
this.socket.sendUTF(JSON.stringify(obj));
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
const { Client } = require("../Client.js");
|
||||||
|
let {randomUUID} = require("crypto");
|
||||||
|
let {addService,addListener} = require("../WebSocket.js");
|
||||||
|
const { Room } = require("./Room.js");
|
||||||
|
let term = require("terminal-kit").terminal;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Peer to peer veri aktarımı
|
||||||
|
|
||||||
|
- Kişiden kişiye direkt veri aktarımı
|
||||||
|
- Kişiler arası tünelleme / Kişiler arası özel protokol
|
||||||
|
- Oda katılımcıları içerisinde veri aktarımı
|
||||||
|
- Oda katılımcıları arasında belli kişilere veri aktarımı
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
addService(({
|
||||||
|
client,
|
||||||
|
end,
|
||||||
|
global,
|
||||||
|
message,
|
||||||
|
next,
|
||||||
|
response
|
||||||
|
}) => {
|
||||||
|
let {type} = message;
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case "pack/to":{
|
||||||
|
let {to,pack} = message;
|
||||||
|
if(Client.clients.has(to))
|
||||||
|
{
|
||||||
|
Client.clients.get(to).send([{
|
||||||
|
from: client.id,
|
||||||
|
pack: pack
|
||||||
|
}, 'pack']);
|
||||||
|
end({
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
end({
|
||||||
|
type: 'fail'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "pack/room":{
|
||||||
|
let {to,pack} = message;
|
||||||
|
if(Room.rooms.has(to))
|
||||||
|
{
|
||||||
|
if(!client.rooms.has(to))
|
||||||
|
{
|
||||||
|
return end({
|
||||||
|
type: 'fail'
|
||||||
|
})
|
||||||
|
};
|
||||||
|
Room.rooms.get(to).send([{
|
||||||
|
from: client.id,
|
||||||
|
pack: pack
|
||||||
|
}, 'pack']);
|
||||||
|
end({
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
end({
|
||||||
|
type: 'fail'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:{
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
|
@ -1,9 +1,14 @@
|
||||||
const { Client } = require("../Client.js");
|
const { Client } = require("../Client.js");
|
||||||
let {randomUUID} = require("crypto");
|
let {randomUUID,createHash} = require("crypto");
|
||||||
const joi = require("joi");
|
const joi = require("joi");
|
||||||
let {addService,addListener} = require("../WebSocket.js");
|
let {addService,addListener} = require("../WebSocket.js");
|
||||||
let term = require("terminal-kit").terminal;
|
let term = require("terminal-kit").terminal;
|
||||||
|
|
||||||
|
function Sha256(update)
|
||||||
|
{
|
||||||
|
return createHash("sha256").update(update).digest("hex");
|
||||||
|
};
|
||||||
|
|
||||||
function Room()
|
function Room()
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -53,7 +58,7 @@ function Room()
|
||||||
/**
|
/**
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
this.password = null;
|
this.credential = null;
|
||||||
/**
|
/**
|
||||||
* @type {string[]}
|
* @type {string[]}
|
||||||
*/
|
*/
|
||||||
|
@ -103,7 +108,6 @@ Room.prototype.join = function(client){
|
||||||
Room.prototype.down = function(){
|
Room.prototype.down = function(){
|
||||||
term.red("Room is downed ").red(this.name," in ").yellow(this.clients.size + "").red(" clients")('\n');
|
term.red("Room is downed ").red(this.name," in ").yellow(this.clients.size + "").red(" clients")('\n');
|
||||||
this.send([{
|
this.send([{
|
||||||
id: client.id,
|
|
||||||
roomid: this.id,
|
roomid: this.id,
|
||||||
ownerid: this.owner.id
|
ownerid: this.owner.id
|
||||||
},'room/closed']);
|
},'room/closed']);
|
||||||
|
@ -123,6 +127,13 @@ Room.prototype.eject = function(client){
|
||||||
}
|
}
|
||||||
client.rooms.delete(this.id);
|
client.rooms.delete(this.id);
|
||||||
this.clients.delete(client.id);
|
this.clients.delete(client.id);
|
||||||
|
|
||||||
|
if(this.clients.size == 0)
|
||||||
|
{
|
||||||
|
this.down();
|
||||||
|
term.red("Client Room closed ").red(this.name," at 0 clients")('\n');
|
||||||
|
}
|
||||||
|
|
||||||
term.red("Client Room ejected ").red(this.name," in ").yellow(this.clients.size + "").red(" clients")('\n');
|
term.red("Client Room ejected ").red(this.name," in ").yellow(this.clients.size + "").red(" clients")('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -159,7 +170,8 @@ let CreateRoomVerify = joi.object({
|
||||||
notifyActionEjected: joi.boolean().required(),
|
notifyActionEjected: joi.boolean().required(),
|
||||||
joinType: joi.string().pattern(/^free$|^invite$|^password$|^lock$/).required(),
|
joinType: joi.string().pattern(/^free$|^invite$|^password$|^lock$/).required(),
|
||||||
description: joi.string().required(),
|
description: joi.string().required(),
|
||||||
name: joi.string().required()
|
name: joi.string().required(),
|
||||||
|
credential: joi.string().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
addService(({
|
addService(({
|
||||||
|
@ -175,7 +187,27 @@ addService(({
|
||||||
{
|
{
|
||||||
case 'myroom-info':{
|
case 'myroom-info':{
|
||||||
let room = Room.rooms.get(client.id);
|
let room = Room.rooms.get(client.id);
|
||||||
end(room.toJSON())
|
end({
|
||||||
|
status: "success",
|
||||||
|
room: room.toJSON()
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'room-peers':{
|
||||||
|
let {roomId} = message;
|
||||||
|
if(Room.rooms.has(roomId))
|
||||||
|
{
|
||||||
|
end({
|
||||||
|
status: 'success',
|
||||||
|
peers: [
|
||||||
|
...Room.rooms.get(roomId).clients.values()
|
||||||
|
].map(i => i.id)
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
end({
|
||||||
|
status: 'fail'
|
||||||
|
})
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'room-info':{
|
case 'room-info':{
|
||||||
|
@ -189,7 +221,7 @@ addService(({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return end({
|
end({
|
||||||
status : "fail",
|
status : "fail",
|
||||||
message : "NOT-FOUND-ROOM"
|
message : "NOT-FOUND-ROOM"
|
||||||
})
|
})
|
||||||
|
@ -204,6 +236,29 @@ addService(({
|
||||||
end(data)
|
end(data)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'closeroom':{
|
||||||
|
let {roomId} = message;
|
||||||
|
if(Room.rooms.has(roomId))
|
||||||
|
{
|
||||||
|
let room = Room.rooms.get(roomId);
|
||||||
|
if(room.owner === client.id)
|
||||||
|
{
|
||||||
|
room.down();
|
||||||
|
end({
|
||||||
|
status: 'success'
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
end({
|
||||||
|
status: 'fail'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
end({
|
||||||
|
status: 'fail'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'create-room':{
|
case 'create-room':{
|
||||||
let {error} = CreateRoomVerify.validate(message);
|
let {error} = CreateRoomVerify.validate(message);
|
||||||
if(error)
|
if(error)
|
||||||
|
@ -232,6 +287,10 @@ addService(({
|
||||||
room.description = message.description;
|
room.description = message.description;
|
||||||
room.name = message.name;
|
room.name = message.name;
|
||||||
room.owner = client;
|
room.owner = client;
|
||||||
|
if(message.credential)
|
||||||
|
{
|
||||||
|
room.credential = Sha256(message.credential + "");
|
||||||
|
}
|
||||||
room.join(client);
|
room.join(client);
|
||||||
room.publish();
|
room.publish();
|
||||||
end({
|
end({
|
||||||
|
@ -263,17 +322,24 @@ addService(({
|
||||||
})
|
})
|
||||||
}else if(room.joinType == "password")
|
}else if(room.joinType == "password")
|
||||||
{
|
{
|
||||||
if(room.password == message.credential)
|
if(room.credential == Sha256(message.credential + ""))
|
||||||
{
|
{
|
||||||
room.join(client);
|
room.join(client);
|
||||||
return end({status : "success"})
|
return end({
|
||||||
|
status : "success",
|
||||||
|
room: room.toJSON()
|
||||||
|
})
|
||||||
}else return end({
|
}else return end({
|
||||||
status : "fail",
|
status : "fail",
|
||||||
message : "WRONG-PASSWORD"
|
message : "WRONG-PASSWORD",
|
||||||
|
area: "credential"
|
||||||
})
|
})
|
||||||
}else if(room.joinType == "free"){
|
}else if(room.joinType == "free"){
|
||||||
room.join(client);
|
room.join(client);
|
||||||
return end({status : "success"})
|
return end({
|
||||||
|
status : "success",
|
||||||
|
room: room.toJSON()
|
||||||
|
})
|
||||||
}else if(room.joinType == "invite"){
|
}else if(room.joinType == "invite"){
|
||||||
room.waitingInvited.add(client.id);
|
room.waitingInvited.add(client.id);
|
||||||
if(room.notifyActionInvite)
|
if(room.notifyActionInvite)
|
||||||
|
@ -295,6 +361,9 @@ addService(({
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:{
|
||||||
|
next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -20,18 +20,19 @@ let global = new Map();
|
||||||
let clients = new Map();
|
let clients = new Map();
|
||||||
wsServer.addListener("connect",(socket) => {
|
wsServer.addListener("connect",(socket) => {
|
||||||
|
|
||||||
let local = new Client();
|
let xClient = new Client();
|
||||||
let id = randomUUID();
|
let id = randomUUID();
|
||||||
socket.id = id;
|
socket.id = id;
|
||||||
local.id = id;
|
xClient.id = id;
|
||||||
local.socket = socket;
|
xClient.socket = socket;
|
||||||
local.created_at = new Date();
|
xClient.created_at = new Date();
|
||||||
clients.set(id, local);
|
Client.clients.set(id, xClient);
|
||||||
|
clients.set(id, xClient);
|
||||||
|
|
||||||
emit("connect", global, local);
|
emit("connect", global, xClient);
|
||||||
socket.addListener("close",()=>{
|
socket.addListener("close",()=>{
|
||||||
emit("disconnect", global, local);
|
emit("disconnect", global, xClient);
|
||||||
clients.delete(id);
|
Client.clients.set(id, xClient);
|
||||||
});
|
});
|
||||||
socket.addListener("message",({type,utf8Data}) => {
|
socket.addListener("message",({type,utf8Data}) => {
|
||||||
if(type == "utf8")
|
if(type == "utf8")
|
||||||
|
@ -39,15 +40,15 @@ wsServer.addListener("connect",(socket) => {
|
||||||
let json;
|
let json;
|
||||||
try{
|
try{
|
||||||
json = JSON.parse(utf8Data);
|
json = JSON.parse(utf8Data);
|
||||||
emit('services', global, local, json);
|
emit('services', global, xClient, json);
|
||||||
let [payload, id, action] = json;
|
let [payload, id, action] = json;
|
||||||
if(typeof id === "string")
|
if(typeof id === "string")
|
||||||
{
|
{
|
||||||
action = id;
|
action = id;
|
||||||
}
|
}
|
||||||
emitService(global, local, id, payload, action);
|
emitService(global, xClient, id, payload, action);
|
||||||
}catch{
|
}catch{
|
||||||
emit("messageError", global, local, utf8Data);
|
emit("messageError", global, xClient, utf8Data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -96,7 +97,7 @@ function emit(event,...args)
|
||||||
* @param {Client} local
|
* @param {Client} local
|
||||||
* @param {number} id
|
* @param {number} id
|
||||||
* @param {{[key:string]:any}} payload
|
* @param {{[key:string]:any}} payload
|
||||||
* @param {"R"|"S"} action
|
* @param {"R"|"S"} action [R]EQUEST flag or [S]TREAM flag
|
||||||
*/
|
*/
|
||||||
async function emitService(global, client, id, payload, action)
|
async function emitService(global, client, id, payload, action)
|
||||||
{
|
{
|
||||||
|
@ -108,10 +109,10 @@ async function emitService(global, client, id, payload, action)
|
||||||
client,
|
client,
|
||||||
global,
|
global,
|
||||||
response:(obj)=>{
|
response:(obj)=>{
|
||||||
client.send([obj, id, 'C']) // continue
|
client.send([obj, id, 'C']) // continue ([C]ONTINUE flag)
|
||||||
},
|
},
|
||||||
end:(obj)=>{
|
end:(obj)=>{
|
||||||
client.send([obj, id, 'E']) // stopped data stream (this channel)
|
client.send([obj, id, 'E']) // stopped data stream (this channel) ([E]ND flag)
|
||||||
},
|
},
|
||||||
next:function(){
|
next:function(){
|
||||||
willContinue = true;
|
willContinue = true;
|
||||||
|
|
|
@ -3,4 +3,5 @@ require("./WebSocket.js");
|
||||||
|
|
||||||
require("./Services/YourID.js");
|
require("./Services/YourID.js");
|
||||||
require("./Services/Auth.js");
|
require("./Services/Auth.js");
|
||||||
require("./Services/Room.js");
|
require("./Services/Room.js");
|
||||||
|
require("./Services/DataTransfer.js");
|
36
test.html
36
test.html
|
@ -16,18 +16,39 @@
|
||||||
console.log("Connected ws")
|
console.log("Connected ws")
|
||||||
let roomInfo = await ws.roomInfo("MY-ROOM");
|
let roomInfo = await ws.roomInfo("MY-ROOM");
|
||||||
console.log("Room Info", roomInfo)
|
console.log("Room Info", roomInfo)
|
||||||
|
|
||||||
|
let type = "";
|
||||||
|
|
||||||
if(roomInfo.status == 'fail' && roomInfo.message == "NOT-FOUND-ROOM")
|
if(roomInfo.status == 'fail' && roomInfo.message == "NOT-FOUND-ROOM")
|
||||||
{
|
{
|
||||||
let secretRoom = await ws.createRoom({
|
type = "owner";
|
||||||
|
roomInfo = await ws.createRoom({
|
||||||
name: "MY-ROOM",
|
name: "MY-ROOM",
|
||||||
description: "Gizli Odam",
|
description: "Gizli Odam",
|
||||||
joinType: "free"
|
joinType: "password",
|
||||||
|
credential: "123456Kc"
|
||||||
});
|
});
|
||||||
console.log("CreateRoom",secretRoom);
|
|
||||||
|
|
||||||
|
setInterval(()=>{
|
||||||
|
ws.sendPackToRoom( roomInfo.room.id,"Merhaba");
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
let joinedRoom = await ws.joinRoom("MY-ROOM");
|
roomInfo = await ws.joinRoom({name:"MY-ROOM",credential:"123456Kc"});
|
||||||
console.log("JoinRoom",joinedRoom);
|
|
||||||
}
|
setInterval(()=>{
|
||||||
|
ws.sendPackToPeer( roomInfo.room.owner,"Merhaba Yönetici");
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
type = "member";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
console.log("Oda bilgisi: ",roomInfo);
|
||||||
|
let Peers = await ws.getRoomPeers( roomInfo.room.id);
|
||||||
|
|
||||||
|
console.log("Odadaki eşlerin bilgisi: ",Peers)
|
||||||
|
|
||||||
console.log(await ws.getJoinedRooms());
|
console.log(await ws.getJoinedRooms());
|
||||||
|
|
||||||
|
@ -35,6 +56,9 @@
|
||||||
ws.signal('id',(data)=>{
|
ws.signal('id',(data)=>{
|
||||||
console.log("Your id is ", data.value)
|
console.log("Your id is ", data.value)
|
||||||
});
|
});
|
||||||
|
ws.signal('pack',(pack)=>{
|
||||||
|
console.log("Recaived Package :", pack)
|
||||||
|
});
|
||||||
ws.signal("room/joined",(joinStatus)=>{
|
ws.signal("room/joined",(joinStatus)=>{
|
||||||
console.log("Room joined", joinStatus)
|
console.log("Room joined", joinStatus)
|
||||||
});
|
});
|
||||||
|
|
112
wsjs.js
112
wsjs.js
|
@ -31,11 +31,11 @@ WSJS.prototype.messageEvent = function({data}){
|
||||||
this.requests.get(id)(payload, action);
|
this.requests.get(id)(payload, action);
|
||||||
switch(action)
|
switch(action)
|
||||||
{
|
{
|
||||||
case 'E':{
|
case 'E':{ // [E]ND flag
|
||||||
this.requests.delete(id);
|
this.requests.delete(id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'S':
|
case 'S': // [S]TREAM flag
|
||||||
default:{
|
default:{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,7 @@ WSJS.prototype.sendRaw = function(obj){
|
||||||
this.ws.send(JSON.stringify(obj))
|
this.ws.send(JSON.stringify(obj))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
WSJS.prototype.checkAuth = async function(username, password){
|
WSJS.prototype.checkAuth = async function(username, password){
|
||||||
return false;
|
return false;
|
||||||
let {value:isAuth} = await this.request({
|
let {value:isAuth} = await this.request({
|
||||||
|
@ -121,67 +122,70 @@ WSJS.prototype.checkAuth = async function(username, password){
|
||||||
});
|
});
|
||||||
return isAuth;
|
return isAuth;
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
WSJS.prototype.authWith = async function(username, password){
|
WSJS.prototype.authWith = async function(username, password){
|
||||||
if(!await this.checkAuth())
|
await this.request({
|
||||||
{
|
type: 'auth/login',
|
||||||
await this.request({
|
username,
|
||||||
type: 'auth/login',
|
password
|
||||||
username,
|
});
|
||||||
password
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
WSJS.prototype.fetchMyRoomInfo = async function(){
|
WSJS.prototype.fetchMyRoomInfo = async function(){
|
||||||
if(!await this.checkAuth())
|
return await this.request({
|
||||||
{
|
type: 'myroom-info'
|
||||||
return await this.request({
|
});
|
||||||
type: 'myroom-info'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
WSJS.prototype.createRoom = async function(options){
|
WSJS.prototype.createRoom = async function(options){
|
||||||
if(!await this.checkAuth())
|
let result = await this.request({
|
||||||
{
|
type: 'create-room',
|
||||||
let result = await this.request({
|
accessType: options.accessType || "private",
|
||||||
type: 'create-room',
|
notifyActionInvite: options.notifyActionInvite === undefined ? true : options.notifyActionInvite,
|
||||||
accessType: options.accessType || "public",
|
notifyActionJoined: options.notifyActionJoined === undefined ? true : options.notifyActionJoined,
|
||||||
notifyActionInvite:options.notifyActionInvite || true,
|
notifyActionEjected: options.notifyActionEjected === undefined ? true : options.notifyActionEjected,
|
||||||
notifyActionJoined: options.notifyActionJoined || true,
|
joinType: options.joinType || "free",
|
||||||
notifyActionEjected: options.notifyActionEjected || true,
|
description: options.description || "No Description",
|
||||||
joinType: options.joinType || "free",
|
name: options.name || "No",
|
||||||
description: options.description || "No Description",
|
credential: options.credential || undefined
|
||||||
name: options.name || "No"
|
});
|
||||||
|
return result;
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
WSJS.prototype.roomInfo = async function(name){
|
WSJS.prototype.roomInfo = async function(name){
|
||||||
if(!await this.checkAuth())
|
let result = await this.request({
|
||||||
{
|
type: 'room-info',
|
||||||
let result = await this.request({
|
name
|
||||||
type: 'room-info',
|
});
|
||||||
name
|
return result;
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
WSJS.prototype.joinRoom = async function(name){
|
WSJS.prototype.joinRoom = async function(options){
|
||||||
if(!await this.checkAuth())
|
let result = await this.request({
|
||||||
{
|
...options,
|
||||||
let result = await this.request({
|
type: 'joinroom'
|
||||||
type: 'joinroom',
|
});
|
||||||
name
|
return result;
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
WSJS.prototype.joinedRooms = new Map();
|
WSJS.prototype.joinedRooms = new Map();
|
||||||
WSJS.prototype.getJoinedRooms = async function(){
|
WSJS.prototype.getJoinedRooms = async function(){
|
||||||
if(!await this.checkAuth())
|
return await this.request({
|
||||||
{
|
type: 'joinedrooms'
|
||||||
return await this.request({
|
});
|
||||||
type: 'joinedrooms'
|
};
|
||||||
});
|
WSJS.prototype.getRoomPeers = async function(id){
|
||||||
}
|
return await this.request({
|
||||||
|
type: 'room-peers',
|
||||||
|
roomId: id
|
||||||
|
});
|
||||||
|
};
|
||||||
|
WSJS.prototype.sendPackToPeer = async function(roomId, pack){
|
||||||
|
return await this.request({
|
||||||
|
type: 'pack/to',
|
||||||
|
to: roomId,
|
||||||
|
pack
|
||||||
|
});
|
||||||
|
};
|
||||||
|
WSJS.prototype.sendPackToRoom = async function(roomId, pack){
|
||||||
|
return await this.request({
|
||||||
|
type: 'pack/room',
|
||||||
|
to: roomId,
|
||||||
|
pack
|
||||||
|
});
|
||||||
};
|
};
|
Loading…
Reference in New Issue