broadcast synced
This commit is contained in:
parent
3da02a89a7
commit
3bc56bf91e
8 changed files with 170 additions and 42 deletions
51
package-lock.json
generated
51
package-lock.json
generated
|
@ -35,7 +35,8 @@
|
|||
"speakeasy": "^2.0.0",
|
||||
"sqlite3": "^5.1.7",
|
||||
"typeorm": "^0.3.20",
|
||||
"uuid": "^10.0.0"
|
||||
"uuid": "^10.0.0",
|
||||
"yjs": "^13.6.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cors": "^2.8.14",
|
||||
|
@ -2163,6 +2164,16 @@
|
|||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
||||
},
|
||||
"node_modules/isomorphic.js": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz",
|
||||
"integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "GitHub Sponsors ❤",
|
||||
"url": "https://github.com/sponsors/dmonad"
|
||||
}
|
||||
},
|
||||
"node_modules/jackspeak": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
|
||||
|
@ -2220,6 +2231,27 @@
|
|||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/lib0": {
|
||||
"version": "0.2.99",
|
||||
"resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.99.tgz",
|
||||
"integrity": "sha512-vwztYuUf1uf/1zQxfzRfO5yzfNKhTtgOByCruuiQQxWQXnPb8Itaube5ylofcV0oM0aKal9Mv+S1s1Ky0UYP1w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"isomorphic.js": "^0.2.4"
|
||||
},
|
||||
"bin": {
|
||||
"0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js",
|
||||
"0gentesthtml": "bin/gentesthtml.js",
|
||||
"0serve": "bin/0serve.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"funding": {
|
||||
"type": "GitHub Sponsors ❤",
|
||||
"url": "https://github.com/sponsors/dmonad"
|
||||
}
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
|
@ -4799,6 +4831,23 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/yjs": {
|
||||
"version": "13.6.23",
|
||||
"resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.23.tgz",
|
||||
"integrity": "sha512-ExtnT5WIOVpkL56bhLeisG/N5c4fmzKn4k0ROVfJa5TY2QHbH7F0Wu2T5ZhR7ErsFWQEFafyrnSI8TPKVF9Few==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lib0": "^0.2.99"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0",
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "GitHub Sponsors ❤",
|
||||
"url": "https://github.com/sponsors/dmonad"
|
||||
}
|
||||
},
|
||||
"node_modules/yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
|
|
|
@ -50,7 +50,8 @@
|
|||
"speakeasy": "^2.0.0",
|
||||
"sqlite3": "^5.1.7",
|
||||
"typeorm": "^0.3.20",
|
||||
"uuid": "^10.0.0"
|
||||
"uuid": "^10.0.0",
|
||||
"yjs": "^13.6.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cors": "^2.8.14",
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import * as Y from "yjs";
|
||||
|
||||
export interface missionStoreModel {
|
||||
missionId: string;
|
||||
doc: any;
|
||||
doc: Y.Doc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Server, Socket } from "socket.io";
|
||||
import { SocketMap } from "../../storage/socketMap";
|
||||
import CustomRequestException from "../../exceptions/customRequestException";
|
||||
import { MissionMap } from "../../storage/missionMap";
|
||||
|
||||
export default (io: Server, socket: Socket) => {
|
||||
socket.on("ping", (callback: Function) => {
|
||||
|
@ -28,6 +29,13 @@ export default (io: Server, socket: Socket) => {
|
|||
|
||||
socket.on("disconnecting", () => {
|
||||
console.log("socket disconnection: ", socket.id);
|
||||
const socketRooms = Array.from(socket.rooms).filter((room) => room !== socket.id && room !== "home");
|
||||
socket.leave(socketRooms[0]);
|
||||
|
||||
const clients = io.sockets.adapter.rooms.get(socketRooms[0]);
|
||||
if (!clients || clients.size == 0) {
|
||||
MissionMap.delete(socketRooms[0]);
|
||||
}
|
||||
SocketMap.delete(socket.id);
|
||||
});
|
||||
|
||||
|
|
101
src/websocket/endpoints/missionManagement.ts
Normal file
101
src/websocket/endpoints/missionManagement.ts
Normal file
|
@ -0,0 +1,101 @@
|
|||
import { Server, Socket } from "socket.io";
|
||||
import { handleEvent } from "../handleEvent";
|
||||
import { MissionMap } from "../../storage/missionMap";
|
||||
import * as Y from "yjs";
|
||||
|
||||
export default (io: Server, socket: Socket) => {
|
||||
socket.on(
|
||||
"mission:join",
|
||||
handleEvent(
|
||||
{ type: "read", section: "operation", module: "mission" },
|
||||
async (data: any) => {
|
||||
socket.rooms.forEach((room) => {
|
||||
if (room !== socket.id && room != "home") {
|
||||
socket.leave(room);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
const doc = new Y.Doc();
|
||||
doc.getMap("form");
|
||||
doc.getText("editor");
|
||||
|
||||
// const ymap = ydoc.getMap('myMap');
|
||||
// ymap.set('titel', 'Mein Dokument');
|
||||
// ymap.set('inhalt', 'Hier ist der initiale Inhalt');
|
||||
// ymap.set('erstelltAm', new Date().toISOString());
|
||||
|
||||
// const yarray = ydoc.getArray('meineArray');
|
||||
// yarray.push(['Element 1', 'Element 2', 'Element 3']);
|
||||
|
||||
// const ytext = ydoc.getText('meinText');
|
||||
// ytext.insert(0, 'Hier ist ein initialer Text');
|
||||
|
||||
// get mission data
|
||||
MissionMap.write(data, {
|
||||
missionId: data,
|
||||
doc,
|
||||
});
|
||||
|
||||
const mission = MissionMap.read(data);
|
||||
|
||||
socket.join(data);
|
||||
socket.emit("status-mission:join", { status: "success" });
|
||||
return {
|
||||
type: "package-mission",
|
||||
answer: Y.encodeStateAsUpdate(mission.doc),
|
||||
};
|
||||
} catch (error) {
|
||||
return { type: "status-join:join", answer: { status: "failed", msg: error.message } };
|
||||
}
|
||||
},
|
||||
socket
|
||||
)
|
||||
);
|
||||
|
||||
socket.on(
|
||||
"mission:sync",
|
||||
handleEvent(
|
||||
{ type: "read", section: "operation", module: "mission" },
|
||||
async (data: any) => {
|
||||
const socketRooms = Array.from(socket.rooms).filter((room) => room !== socket.id && room !== "home");
|
||||
try {
|
||||
const mission = MissionMap.read(socketRooms[0]);
|
||||
Y.applyUpdate(mission.doc, new Uint8Array(data));
|
||||
|
||||
socket.emit("status-mission:sync", { status: "success" });
|
||||
return {
|
||||
type: "package-sync",
|
||||
answer: data,
|
||||
room: socketRooms[0],
|
||||
};
|
||||
} catch (error) {
|
||||
return { type: "status-mission:sync", answer: { status: "failed", msg: error.message } };
|
||||
}
|
||||
},
|
||||
socket
|
||||
)
|
||||
);
|
||||
|
||||
socket.on(
|
||||
"mission:leave",
|
||||
handleEvent(
|
||||
{ type: "read", section: "operation", module: "mission" },
|
||||
async (data: any) => {
|
||||
const socketRooms = Array.from(socket.rooms).filter((room) => room !== socket.id && room !== "home");
|
||||
socket.leave(socketRooms[0]);
|
||||
|
||||
const clients = io.sockets.adapter.rooms.get(socketRooms[0]);
|
||||
if (!clients || clients.size == 0) {
|
||||
MissionMap.delete(socketRooms[0]);
|
||||
}
|
||||
|
||||
return {
|
||||
type: "deleted",
|
||||
answer: "leave instance",
|
||||
};
|
||||
},
|
||||
socket
|
||||
)
|
||||
);
|
||||
};
|
|
@ -1,36 +0,0 @@
|
|||
import { Server, Socket } from "socket.io";
|
||||
import { SocketMap } from "../../storage/socketMap";
|
||||
import CustomRequestException from "../../exceptions/customRequestException";
|
||||
import { handleEvent } from "../handleEvent";
|
||||
|
||||
export default (io: Server, socket: Socket) => {
|
||||
socket.on(
|
||||
"join:mission",
|
||||
|
||||
handleEvent(
|
||||
{ type: "read", section: "operation", module: "mission" },
|
||||
async (data: any) => {
|
||||
socket.rooms.forEach((room) => {
|
||||
if (room !== socket.id && room != "home") {
|
||||
socket.leave(room);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
socket.join(data);
|
||||
socket.emit("status-mission:room", { status: "success" });
|
||||
// get mission data
|
||||
// create yjs sync doc
|
||||
// provide yjs sync doc to client
|
||||
return {
|
||||
type: "package-mission",
|
||||
answer: "mission-data by yjs",
|
||||
};
|
||||
} catch (error) {
|
||||
return { type: "status-join:room", answer: { status: "failed", msg: error.message } };
|
||||
}
|
||||
},
|
||||
socket
|
||||
)
|
||||
);
|
||||
};
|
|
@ -38,7 +38,10 @@ export let handleEvent = (
|
|||
throw new ForbiddenRequestException(`missing admin permission`);
|
||||
}
|
||||
} else {
|
||||
if (!PermissionHelper.can(socketData.permissions, permissions.type, permissions.section, permissions.module)) {
|
||||
if (
|
||||
!socketData.isOwner &&
|
||||
!PermissionHelper.can(socketData.permissions, permissions.type, permissions.section, permissions.module)
|
||||
) {
|
||||
throw new ForbiddenRequestException(`missing required permission`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Server } from "socket.io";
|
|||
import authenticateSocket from "./middleware/authenticateSocket";
|
||||
import base from "./endpoints/base";
|
||||
import perRequestCheck from "./middleware/perRequestCheck";
|
||||
import roomManagement from "./endpoints/roomManagement";
|
||||
import missionManagement from "./endpoints/missionManagement";
|
||||
|
||||
export default abstract class SocketServer {
|
||||
private static io: Server;
|
||||
|
@ -28,7 +28,7 @@ export default abstract class SocketServer {
|
|||
socket.use((packet, next) => perRequestCheck(socket, packet, next));
|
||||
|
||||
base(this.io, socket);
|
||||
roomManagement(this.io, socket);
|
||||
missionManagement(this.io, socket);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue