Room logic part 1/3

This commit is contained in:
Abdussamed ULUTAŞ 2022-11-17 23:06:05 +03:00
parent 08e8c59d59
commit 8ec6380aea
8 changed files with 371 additions and 7 deletions

View File

@ -20,4 +20,6 @@ Client.prototype.send = function(obj){
this.socket.sendUTF(JSON.stringify(obj));
};
Client.prototype.rooms = new Set();
exports.Client = Client;

View File

@ -1,12 +1,10 @@
let {addService} = require("../WebSocket.js");
addService(({
global,
client,
message,
end,
next,
response
next
})=>{
let {type,username,password} = message;
if(type === 'auth/check')
@ -44,4 +42,5 @@ addService(({
})
}
};
next();
});

240
Source/Services/Room.js Normal file
View File

@ -0,0 +1,240 @@
const { Client } = require("../Client.js");
let {randomUUID} = require("crypto");
const joi = require("joi");
let {addService,addListener} = require("../WebSocket.js");
function Room()
{
/**
* @type {string}
*/
this.id = randomUUID();
/**
* @type {string}
*/
this.name = "";
/**
* @type {string}
*/
this.description = "";
/**
* @type {Client}
*/
this.owner = null;
/**
* @type {Date}
*/
this.createdAt = new Date();
/**
* @type {Map<string, Client>}
*/
this.clients = new Map();
/**
* @type {"public"|"private"}
*/
this.accessType = "";
/**
* @type {"free"|"invite"|"password"|"lock"}
*/
this.joinType = "invite";
/**
* @type {boolean}
*/
this.notifyActionInvite = false;
/**
* @type {boolean}
*/
this.notifyActionJoined = true;
/**
* @type {boolean}
*/
this.notifyActionEjected = true;
/**
* @type {string}
*/
this.password = null;
/**
* @type {string[]}
*/
this.waitingInvited = new Set();
}
/**
* @param {Room} room
*/
Room.prototype.publish = function(room){
Room.rooms.set(room.id, room);
};
Room.prototype.toJSON = function(){
let obj = {};
obj.id = this.id;
obj.accessType = this.accessType;
obj.createdAt = this.createdAt;
obj.description = this.description;
obj.joinType = this.joinType;
obj.name = this.name;
obj.owner = this.owner.id;
obj.waitingInvited = [...this.waitingInvited];
return obj;
};
Room.prototype.send = function(obj){
for (const client of this.clients.values()) {
client.send(obj);
}
};
/**
* @param {Client} client
*/
Room.prototype.join = function(client){
this.notifyActionJoined && this.send([{
id: client.id,
roomid: this.id,
ownerid: this.owner.id
},'room/joined']);
client.rooms.add(this.id);
this.clients.set(client.id, client);
};
Room.prototype.active = function(){
Room.rooms.set(this.id, this);
};
Room.prototype.deactive = function(){
Room.rooms.delete(this.id);
};
/**
* @param {Client} client
*/
Room.prototype.eject = function(client){
this.notifyActionEjected && this.send([{
id: client.id,
roomid: this.id,
ownerid: this.owner.id
},'room/ejected']);
client.rooms.delete(this.id);
this.clients.delete(client.id);
};
/**
* @type {Map<string, Room>}
*/
Room.rooms = new Map();
addListener('connect',(global, client)=>{
let room = new Room();
room.accessType = "private";
room.joinType = "notify";
room.clients.set(client.id, client);
room.description = 'Yourself private room, you can invite friends';
room.id = client.id;
room.name = "Your Room";
room.owner = client;
room.join(client);
room.active();
});
addListener('disconnect',(global, client)=>{
for (const roomId of client.rooms) {
Room.rooms.get(roomId).eject(client);
Room.rooms.get(roomId).deactive();
}
});
let CreateRoomVerify = joi.object({
type: joi.any().required(),
accessType: joi.string().pattern(/^public$|private$/).required(),
notifyActionInvite: joi.boolean().required(),
notifyActionJoined: joi.boolean().required(),
notifyActionEjected: joi.boolean().required(),
joinType: joi.string().pattern(/^free$|^invite$|^password$|^lock$/).required(),
description: joi.string().required(),
name: joi.string().required()
});
addService(({
client,
end,
global,
message,
next,
response
})=>{
let {type} = message;
switch(type)
{
case 'myroom-info':{
let room = Room.rooms.get(client.id);
end(room.toJSON())
break;
}
case 'create-room':{
let {error} = CreateRoomVerify.validate(message);
if(error)
{
return end({
status: 'fail',
messages: error.message
})
}else{
let room = new Room();
room.accessType = message.accessType;
room.notifyActionInvite = message.notifyActionInvite;
room.notifyActionJoined = message.notifyActionJoined;
room.notifyActionEjected = message.notifyActionEjected;
room.joinType = message.joinType;
room.description = message.description;
room.name = message.name;
room.owner = client;
room.join(client);
room.active();
end(room.toJSON())
}
break;
}
case 'join':{
let isRoom = Room.rooms.has(client.id);
if(isRoom)
{
let room = Room.rooms.get(client.id);
if(room.joinType == "lock")
{
return end({
status : "fail",
message : "LOCKED-ROOM"
})
}else if(room.joinType == "password")
{
if(room.password == message.credential)
{
room.join(client);
return end({status : "success"})
}else return end({
status : "fail",
message : "WRONG-PASSWORD"
})
}else if(room.joinType == "free"){
room.join(client);
}else if(room.joinType == "invite"){
room.waitingInvited.add(client.id);
if(room.notifyActionInvite)
{
room.send([{
id: client.id
},"room/invite"]);
}else{
room.owner.send([{
id: client.id
},"room/invite"]);
}
};
}else{
return end({
status : "fail",
message : "NOT-FOUND-ROOM"
})
}
break;
}
}
});
exports.Room = Room;

View File

@ -2,4 +2,5 @@ require("./HTTPServer.js");
require("./WebSocket.js");
require("./Services/YourID.js");
require("./Services/Auth.js");
require("./Services/Auth.js");
require("./Services/Room.js");

87
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"joi": "^17.7.0",
"knex": "^2.3.0",
"sqlite3": "^5.1.2",
"websocket": "^1.0.34"
@ -20,6 +21,19 @@
"integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
"optional": true
},
"node_modules/@hapi/hoek": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
"integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="
},
"node_modules/@hapi/topo": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
"integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
"dependencies": {
"@hapi/hoek": "^9.0.0"
}
},
"node_modules/@mapbox/node-pre-gyp": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz",
@ -63,6 +77,24 @@
"node": ">=10"
}
},
"node_modules/@sideway/address": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
"integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==",
"dependencies": {
"@hapi/hoek": "^9.0.0"
}
},
"node_modules/@sideway/formula": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz",
"integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg=="
},
"node_modules/@sideway/pinpoint": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="
},
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@ -616,6 +648,18 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"optional": true
},
"node_modules/joi": {
"version": "17.7.0",
"resolved": "https://registry.npmjs.org/joi/-/joi-17.7.0.tgz",
"integrity": "sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg==",
"dependencies": {
"@hapi/hoek": "^9.0.0",
"@hapi/topo": "^5.0.0",
"@sideway/address": "^4.1.3",
"@sideway/formula": "^3.0.0",
"@sideway/pinpoint": "^2.0.0"
}
},
"node_modules/knex": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/knex/-/knex-2.3.0.tgz",
@ -1470,6 +1514,19 @@
"integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
"optional": true
},
"@hapi/hoek": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
"integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="
},
"@hapi/topo": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
"integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
"requires": {
"@hapi/hoek": "^9.0.0"
}
},
"@mapbox/node-pre-gyp": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz",
@ -1506,6 +1563,24 @@
"rimraf": "^3.0.2"
}
},
"@sideway/address": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
"integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==",
"requires": {
"@hapi/hoek": "^9.0.0"
}
},
"@sideway/formula": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz",
"integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg=="
},
"@sideway/pinpoint": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="
},
"@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@ -1955,6 +2030,18 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"optional": true
},
"joi": {
"version": "17.7.0",
"resolved": "https://registry.npmjs.org/joi/-/joi-17.7.0.tgz",
"integrity": "sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg==",
"requires": {
"@hapi/hoek": "^9.0.0",
"@hapi/topo": "^5.0.0",
"@sideway/address": "^4.1.3",
"@sideway/formula": "^3.0.0",
"@sideway/pinpoint": "^2.0.0"
}
},
"knex": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/knex/-/knex-2.3.0.tgz",

View File

@ -19,6 +19,7 @@
"author": "Abdussamed ULUTAŞ <abdussamedulutas@yandex.com.tr>",
"license": "MIT",
"dependencies": {
"joi": "^17.7.0",
"knex": "^2.3.0",
"sqlite3": "^5.1.2",
"websocket": "^1.0.34"

View File

@ -11,13 +11,23 @@
<script>
let ws = new WSJS();
ws.connect('ws://localhost:8282');
ws.scope(()=>{
ws.scope(async ()=>{
console.log("Connected ws")
ws.authWith("admin","123456Kc");
let roomInfo = await ws.fetchMyRoomInfo();
let secretRoom = await ws.createRoom({
name: "Benim Odam",
description: "Gizli Odam"
});
});
ws.signal('id',(data)=>{
console.log("Your id is ", data.value)
});
ws.signal("room/joined",(joinStatus)=>{
console.log("Room ejected", joinStatus)
});
ws.signal("room/ejected",(ejectStatus)=>{
console.log("Room ejected", ejectStatus)
})
</script>
</body>
</html>

26
wsjs.js
View File

@ -123,11 +123,35 @@ WSJS.prototype.checkAuth = async function(username, password){
WSJS.prototype.authWith = async function(username, password){
if(!await this.checkAuth())
{
let requets = await this.request({
await this.request({
type: 'auth/login',
username,
password
});
}
};
WSJS.prototype.fetchMyRoomInfo = async function(){
if(!await this.checkAuth())
{
return await this.request({
type: 'myroom-info'
});
}
};
WSJS.prototype.createRoom = async function(options){
if(!await this.checkAuth())
{
let result = await this.request({
type: 'create-room',
accessType: options.accessType || "public",
notifyActionInvite:options.notifyActionInvite || true,
notifyActionJoined: options.notifyActionJoined || true,
notifyActionEjected: options.notifyActionEjected || true,
joinType: options.joinType || "free",
description: options.description || "No Description",
name: options.name || "No"
});
debugger;
}
};