summaryrefslogtreecommitdiff
path: root/together/src
diff options
context:
space:
mode:
Diffstat (limited to 'together/src')
-rw-r--r--together/src/index.ts413
-rw-r--r--together/src/types/Session.ts39
-rw-r--r--together/src/types/User.ts44
-rw-r--r--together/src/types/Video.ts41
-rw-r--r--together/src/utils/InternalAPI.ts10
-rw-r--r--together/src/utils/PartyCodes.ts5
6 files changed, 0 insertions, 552 deletions
diff --git a/together/src/index.ts b/together/src/index.ts
deleted file mode 100644
index bfe0d0e..0000000
--- a/together/src/index.ts
+++ /dev/null
@@ -1,413 +0,0 @@
-// pony pone pone pony
-
-import {WebSocket, WebSocketServer} from "ws";
-import {isSessionValid} from "./utils/InternalAPI";
-import User, {APIUser} from "./types/User";
-import Session from "./types/Session";
-import {VideoState} from "./types/Video";
-import {createHash} from 'crypto';
-
-const wss = new WebSocketServer({port: 22666});
-
-let sessions: Map<string, Session> = new Map();
-let partycodes: Map<string, string> = new Map();
-
-wss.on('connection', (ws: WebSocket) => {
- let user: User;
- let timeoutProcess = setTimeout(() => {
- ws.send(JSON.stringify({
- "task": "TERMINATE",
- "payload": {
- "code": "NO_IDENT",
- "reason": "The client did not identify in time."
- }
- }));
-
- ws.close();
- }, 1000);
- ws.on("message", async data => {
- let event = JSON.parse(data.toString()) as WSEvent;
-
- if (event.task === "IDENTIFY") {
- if(user !== undefined) {
- ws.send(JSON.stringify({
- "task": "TERMINATE",
- "payload": {
- "code": "ALREADY_IDENT",
- "reason": "This session has already identified."
- }
- }));
-
- return ws.close();
- }
- clearTimeout(timeoutProcess);
-
- if (["", undefined, null].includes(event.payload["token"]) || typeof event.payload["token"] !== "string") {
- ws.send(JSON.stringify({
- "task": "TERMINATE",
- "payload": {
- "code": "BAD_TOKEN",
- "reason": "The token is not provided or malformed."
- }
- }));
-
- return ws.close();
- }
-
- let tokenValid = await isSessionValid(event.payload["token"]);
-
- if (!tokenValid) {
- ws.send(JSON.stringify({
- "task": "TERMINATE",
- "payload": {
- "code": "INVALID_TOKEN",
- "reason": "The token provided is not valid."
- }
- }));
-
- return ws.close();
- }
-
- ws.send(JSON.stringify({
- "task": "CONFIG",
- "payload": {
- "heartbeatInterval": 100
- }
- }));
-
- timeoutProcess = setTimeout(() => {
- ws.send(JSON.stringify({
- "task": "TERMINATE",
- "payload": {
- "code": "HEARTBEAT_MISS",
- "reason": "The client missed a heartbeat (dead connection)."
- }
- }))
-
- ws.close();
- }, 10000);
-
- user = new User(ws, event.payload["token"]);
- }
- if (event.task == "HEARTBEAT") {
- clearInterval(timeoutProcess);
-
- timeoutProcess = setTimeout(() => {
- ws.send(JSON.stringify({
- "task": "TERMINATE",
- "payload": {
- "code": "HEARTBEAT_MISS",
- "reason": "The client missed a heartbeat (dead connection)."
- }
- }))
-
- ws.close();
- }, 2000);
-
- if(ws["currentSessionId"] !== undefined) {
- let session: Session = sessions.get(ws["currentSessionId"]);
-
- user.videoPositon = event.payload["videoPosition"];
- let index = session.users.findIndex(iuser => iuser.id == user.id);
-
- session.users[index].videoPositon = event.payload["videoPositon"];
-
- sessions.set(session.id, session);
-
- let delays = {};
-
- session.users.forEach(iuser => {
- delays[iuser.id] = Math.floor((iuser.videoPositon * 1000) - (user.videoPositon * 1000));
-
- if(session.currentVideo === null) return;
- if(session.currentVideo.state !== VideoState.Playing) return;
- if(delays[iuser.id] > 1000 || delays[iuser.id] < -1000) {
- ws.send(JSON.stringify({
- "task": "VIDEO_UPDATE",
- "payload": {
- "position": user.videoPositon
- }
- }))
- }
- });
- ws.send(JSON.stringify({
- "task": "HEARTBEAT_ACK",
- "payload": {
- "delays": delays
- }
- }))
- } else {
- ws.send(JSON.stringify({
- "task": "HEARTBEAT_ACK",
- "payload": {
- "delays": []
- }
- }))
- }
- }
- if (event.task == "SESSION") {
- if (event.payload["id"] == null) {
- let session = new Session();
- session.users.push(user);
-
- sessions.set(session.id, session);
- partycodes.set(session.partyCode, session.id);
-
- ws["currentSessionId"] = session.id;
-
- let safeUsers: APIUser[] = [];
-
- session.users.forEach(iuser => {
- safeUsers.push({
- id: iuser.id
- });
- });
-
- ws.send(JSON.stringify({
- "task": "SESSION",
- "payload": {
- "code": session.partyCode,
- "users": safeUsers,
- "queue": session.videoQueue
- }
- }));
-
- /*let video = await user.getYoutubeVideo("wDVLrJESFNI");
- let ongoingVideo = video.toOngoingVideo();
-
- session.currentVideo = ongoingVideo;
-
- sessions.set(session.id, session);
-
- ws.send(JSON.stringify({
- "task": "VIDEO_UPDATE",
- "payload": {
- "url": ongoingVideo.url,
- "title": ongoingVideo.title,
- "author": ongoingVideo.author,
- "thumbnail": ongoingVideo.thumbnail,
- "state": ongoingVideo.state,
- "position": ongoingVideo.position
- }
- }));*/
- } else {
- if (["", undefined, null].includes(event.payload["id"]) || typeof event.payload["id"] != "string") return ws.send(JSON.stringify({
- "task": "FAILURE",
- "payload": {
- "code": "BAD_CODE",
- "reason": "The party code is not present or is malformed."
- }
- }));
-
- if (!partycodes.has(event.payload["id"])) return ws.send(JSON.stringify({
- "task": "FAILURE",
- "payload": {
- "code": "INVALID_CODE",
- "reason": "This party code is not valid."
- }
- }));
-
- let sessionId: string = partycodes.get(event.payload["id"]);
- let session: Session = sessions.get(sessionId);
-
- ws["currentSessionId"] = session.id;
- session.users.push(user);
-
- sessions.set(session.id, session);
-
- let safeUsers: APIUser[] = [];
-
- session.users.forEach(iuser => {
- safeUsers.push({
- id: iuser.id
- });
- });
-
- session.users.forEach(iuser => {
- if (iuser.id == user.id) return;
-
- iuser.ws.send(JSON.stringify({
- "task": "UPDATE_USERS",
- "payload": {
- "users": safeUsers
- }
- }))
- });
-
- ws.send(JSON.stringify({
- "task": "SESSION",
- "payload": {
- "code": session.partyCode,
- "users": safeUsers,
- "queue": session.videoQueue
- }
- }));
-
- if(session.currentVideo != null) {
- ws.send(JSON.stringify({
- "task": "VIDEO_UPDATE",
- "payload": {
- "id": session.currentVideo.id,
- "url": session.currentVideo.url,
- "title": session.currentVideo.title,
- "author": session.currentVideo.author,
- "duration": session.currentVideo.duration,
- "duration_pretty": session.currentVideo.duration_pretty,
- "thumbnail": session.currentVideo.thumbnail,
- "state": session.currentVideo.state,
- "position": session.currentVideo.position
- }
- }));
- }
- }
- }
- if(event.task == "VIDEO_UPDATE") {
- let session: Session = sessions.get(ws["currentSessionId"]);
-
- if (session.currentVideo !== null && session.currentVideo.state === VideoState.Loading) return;
-
- if (session.currentVideo) {
- if(event.payload["state"] === 2) {
- session.currentVideo.state = VideoState.Buffering;
- } else if (event.payload["state"] === 1) {
- session.currentVideo.state = VideoState.Playing;
- } else if (event.payload["state"] === 0) {
- session.currentVideo.state = VideoState.Paused
- }
-
- session.currentVideo.position = event.payload["position"];
-
- if(event.payload["state"] === 0 && Math.floor(event.payload["position"]) >= (session.currentVideo.duration - 1)) {
- console.log("aaaa gotta change (Twi is cute btw)");
-
- session.currentVideo.state = VideoState.Loading;
-
- setTimeout(() => {
- if (session.videoQueue.length === 0) session.currentVideo = null;
- else session.currentVideo = (session.videoQueue.shift()).toOngoingVideo();
-
- if(session.currentVideo !== null) session.currentVideo.state = VideoState.Playing;
-
- session.users.forEach(iuser => {
- iuser.ws.send(JSON.stringify({
- "task": "VIDEO_UPDATE",
- "payload": {
- "id": session.currentVideo ? session.currentVideo.id : null,
- "sha": session.currentVideo ? createHash("sha256").update(session.currentVideo.id).digest("hex") : null,
- "url": session.currentVideo ? session.currentVideo.url : null,
- "title": session.currentVideo ? session.currentVideo.title : null,
- "duration": session.currentVideo ? session.currentVideo.duration : null,
- "duration_pretty": session.currentVideo ? session.currentVideo.duration_pretty : null,
- "author": session.currentVideo ? session.currentVideo.author : null,
- "thumbnail": session.currentVideo ? session.currentVideo.thumbnail : null,
- "state": session.currentVideo ? session.currentVideo.state : null,
- "position": session.currentVideo ? session.currentVideo.position : null
- }
- }));
- iuser.ws.send(JSON.stringify({
- "task": "UPDATE_QUEUE",
- "payload": {
- "queue": session.videoQueue,
- "poster": user.id
- }
- }));
- });
- }, 5000);
- } else {
- session.users.forEach(iuser => {
- if (iuser.id == user.id) return;
-
- iuser.ws.send(JSON.stringify({
- "task": "VIDEO_UPDATE",
- "payload": {
- "state": event.payload["state"],
- "position": event.payload["position"]
- }
- }))
- });
- }
- }
-
- sessions.set(session.id, session);
- }
- if(event.task == "UPDATE_QUEUE") {
- let session: Session = sessions.get(ws["currentSessionId"]);
-
- if(event.payload["operation"] == "+") {
- let video = await user.getYoutubeVideo(event.payload["video"]);
-
- session.videoQueue.push(video);
-
- if(session.videoQueue.length === 1 && session.currentVideo === null) {
- session.currentVideo = (session.videoQueue.shift()).toOngoingVideo();
-
- session.users.forEach(user => {
- user.ws.send(JSON.stringify({
- "task": "VIDEO_UPDATE",
- "payload": {
- "id": session.currentVideo.id,
- "sha": createHash("sha256").update(session.currentVideo.id).digest("hex"),
- "url": session.currentVideo.url,
- "title": session.currentVideo.title,
- "author": session.currentVideo.author,
- "thumbnail": session.currentVideo.thumbnail,
- "state": session.currentVideo.state,
- "position": session.currentVideo.position
- }
- }))
- });
- }
-
- sessions.set(session.id, session);
- }
-
- session.users.forEach(iuser => {
- iuser.ws.send(JSON.stringify({
- "task": "UPDATE_QUEUE",
- "payload": {
- "queue": session.videoQueue,
- "poster": user.id
- }
- }));
- });
- }
- });
-
- ws.on("close", () => {
- if (ws["currentSessionId"] != undefined) {
- if (sessions.has(ws["currentSessionId"])) {
- let session = sessions.get(ws["currentSessionId"]);
- session.users = session.users.filter((iuser) => iuser.id != user.id);
- sessions.set(session.id, session);
- if (session.users.length == 0) {
- sessions.delete(session.id);
- partycodes.delete(session.partyCode);
- } else {
- let safeUsers: APIUser[] = [];
-
- session.users.forEach(iuser => {
- safeUsers.push({
- id: iuser.id
- });
- });
-
- session.users.forEach(iuser => {
- if (iuser.id == user.id) return;
-
- iuser.ws.send(JSON.stringify({
- "task": "UPDATE_USERS",
- "payload": {
- "users": safeUsers
- }
- }))
- });
- }
- }
- }
- });
-});
-
-interface WSEvent {
- task: string,
- payload: object
-} \ No newline at end of file
diff --git a/together/src/types/Session.ts b/together/src/types/Session.ts
deleted file mode 100644
index 5d3e799..0000000
--- a/together/src/types/Session.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import {v4 as uuidv4} from 'uuid';
-import User from "./User";
-import Video, {OngoingVideo} from "./Video";
-import {generateParyCode} from "../utils/PartyCodes";
-
-export default class Session {
- public id: string;
- public partyCode: string;
- public videoQueue: Video[];
- public currentVideo: OngoingVideo;
- public users: User[];
-
- constructor() {
- this.id = uuidv4();
- this.partyCode = generateParyCode();
- this.videoQueue = [];
- this.currentVideo = null;
- this.users = [];
- }
-
- update() {
- if(this.videoQueue.length === 0) this.currentVideo = null;
- else this.currentVideo = (this.videoQueue.shift()).toOngoingVideo();
-
- this.users.forEach(user => {
- user.ws.send(JSON.stringify({
- "task": "VIDEO_UPDATE",
- "payload": {
- "url": this.currentVideo.url,
- "title": this.currentVideo.title,
- "author": this.currentVideo.author,
- "thumbnail": this.currentVideo.thumbnail,
- "state": this.currentVideo.state,
- "position": this.currentVideo.position
- }
- }))
- });
- }
-} \ No newline at end of file
diff --git a/together/src/types/User.ts b/together/src/types/User.ts
deleted file mode 100644
index 900acb8..0000000
--- a/together/src/types/User.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import {WebSocket} from "ws";
-import Video from "./Video";
-import superagent from "superagent";
-
-export default class User {
- public id: string;
- public ws: WebSocket;
- public videoPositon: number;
- private apiToken: string;
-
- constructor(ws: WebSocket, apiToken: string) {
- this.videoPositon = 0;
- this.ws = ws;
- this.apiToken = apiToken;
-
- this.getUserData();
- }
-
- async getUserData() {
- let res = await superagent.get("https://peh-internal.minteck.org/api/me")
- .set("Cookie", "PEH2_SESSION_TOKEN=" + this.apiToken)
- .send();
-
- this.id = res.body["id"];
- }
-
- async getYoutubeVideo(id: string): Promise<Video> {
- let res = await superagent.get("https://peh-internal.minteck.org/api/video?id=" + id)
- .set("Cookie", "PEH2_SESSION_TOKEN=" + this.apiToken)
- .send();
-
- return new Video(id, res.body["title"], res.body["author"], res.body["duration"], res.body["duration_pretty"], res.body["url"], res.body["poster"]);
- }
-
- toAPIUser(): APIUser {
- return {
- id: this.id
- }
- }
-}
-
-export interface APIUser {
- id: string;
-} \ No newline at end of file
diff --git a/together/src/types/Video.ts b/together/src/types/Video.ts
deleted file mode 100644
index 9bba13f..0000000
--- a/together/src/types/Video.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-export default class Video {
- public id: string;
- public title: string;
- public author: string;
- public duration: number;
- public duration_pretty: string;
- public url: string;
- public thumbnail: string;
-
- constructor(id, title, author, duration, duration_pretty, url, thumbnail) {
- this.id = id;
- this.title = title;
- this.author = author;
- this.duration = duration;
- this.duration_pretty = duration_pretty
- this.url = url;
- this.thumbnail = thumbnail;
- }
-
- toOngoingVideo() {
- return new OngoingVideo(this.id, this.title, this.author, this.duration, this.duration_pretty, this.url, this.thumbnail);
- }
-}
-
-export class OngoingVideo extends Video {
- public state: VideoState;
- public position: number;
-
- constructor(id, title, author, duration, duration_pretty, url, thumbnail) {
- super(id, title, author, duration, duration_pretty, url, thumbnail);
- this.state = VideoState.Paused;
- this.position = 0;
- }
-}
-
-export enum VideoState {
- Paused,
- Playing,
- Buffering,
- Loading
-} \ No newline at end of file
diff --git a/together/src/utils/InternalAPI.ts b/together/src/utils/InternalAPI.ts
deleted file mode 100644
index b64f576..0000000
--- a/together/src/utils/InternalAPI.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import superagent from "superagent";
-
-export async function isSessionValid(token: string): Promise<boolean> {
- let res = await superagent.get("https://peh-internal.minteck.org/api/session")
- .set("Cookie", "PEH2_SESSION_TOKEN=" + token)
- .send();
-
- if (res.text === "VALID") return true;
- return false;
-} \ No newline at end of file
diff --git a/together/src/utils/PartyCodes.ts b/together/src/utils/PartyCodes.ts
deleted file mode 100644
index 1acc82e..0000000
--- a/together/src/utils/PartyCodes.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import {randomBytes} from 'crypto';
-
-export function generateParyCode(): string {
- return parseInt(randomBytes(16).toString("hex"), 16).toString(36).substring(0, 8);
-} \ No newline at end of file