diff --git a/package.json b/package.json index 55ecafe..306ac15 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "niwder-api", - "version": "0.1.1", + "version": "0.1.2", "description": "API for Niwder; Download, upload, and go wild with Mega, Google Drive and direct download links.", "main": "dist/index.js", "scripts": { @@ -71,6 +71,7 @@ "morgan": "^1.10.0", "multer": "^1.4.4", "parse-torrent": "^9.1.5", + "socket.io": "^4.5.0", "swagger-ui-express": "^4.3.0", "webtorrent": "^1.8.14", "webtorrent-health": "^1.1.2" diff --git a/src/index.ts b/src/index.ts index 0f627ba..914a3c4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import Keys from "./keys"; import chalk from "chalk"; -import server from "./server"; +import server, { io } from "./server"; import FirebaseService from "./services/FirebaseService"; const { PORT } = Keys; @@ -21,19 +21,11 @@ server.on("close", () => { console.log(chalk.yellow("Niwder-API is shutting down")); }); -process.on("SIGINT", () => { - server.close(async (error) => { - await FirebaseService.setServerDead(interval); - if (error) { - process.exit(1); - } else { - process.exit(0); - } +const shutDownAPI = () => { + io.close((error: Error) => { + if (error) console.log(`Error occurred in Socket.io ${error}`); }); -}); - -process.on("SIGTERM", () => { - server.close(async (error) => { + server.close(async (error: Error) => { await FirebaseService.setServerDead(interval); if (error) { process.exit(1); @@ -41,4 +33,7 @@ process.on("SIGTERM", () => { process.exit(0); } }); -}); +}; + +process.on("SIGINT", shutDownAPI); +process.on("SIGTERM", shutDownAPI); diff --git a/src/keys/index.ts b/src/keys/index.ts index ebc3cfe..76d660b 100644 --- a/src/keys/index.ts +++ b/src/keys/index.ts @@ -25,4 +25,5 @@ export default { OAUTH_REDIRECT_URL: "https://niwder.niweera.gq/transfers", GDRIVE_FOLDER_NAME: "Niwder", MEGA_FOLDER_NAME: "Niwder", + SOCKET_IO_CORS: ["http://localhost:9091", "https://niwder.niweera.gq"], }; diff --git a/src/middleware/socketIOMiddleware.ts b/src/middleware/socketIOMiddleware.ts new file mode 100644 index 0000000..eb95493 --- /dev/null +++ b/src/middleware/socketIOMiddleware.ts @@ -0,0 +1,33 @@ +import { Server as IOServer, Socket } from "socket.io"; +import type { + ClientToServerEvents, + InterServerEvents, + ServerToClientEvents, + SocketData, +} from "../utilities/interfaces"; +import type { Server } from "http"; +import keys from "../keys"; + +export const SetupSocketIO = (server: Server): IOServer => { + const io: IOServer = new IOServer< + ClientToServerEvents, + ServerToClientEvents, + InterServerEvents, + SocketData + >(server, { + cors: { + origin: keys.SOCKET_IO_CORS, + }, + }); + + io.on("connection", (socket: Socket) => { + console.log("socket connected:", socket.connected); + console.log("client connected:", socket.id); + socket.emit("api-alive"); + socket.on("disconnect", () => { + console.log(`client disconnected:`, socket.id); + }); + }); + + return io; +}; diff --git a/src/server/index.ts b/src/server/index.ts index 17900f2..ec04bc3 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -10,6 +10,8 @@ import { import ErrorHandlingMiddleware from "../middleware/error-handling"; import FirebaseAuthMiddleware from "../middleware/firebaser"; import ServeOpenAPI from "../openapi"; +import { SetupSocketIO } from "../middleware/socketIOMiddleware"; +import type { Server as IOServer } from "socket.io"; export const app: Application = express(); app.disable("x-powered-by"); @@ -24,4 +26,5 @@ FirebaseAuthMiddleware(app); app.use("", mainController); ErrorHandlingMiddleware(app); +export const io: IOServer = SetupSocketIO(server); export default server; diff --git a/src/services/FirebaseService.ts b/src/services/FirebaseService.ts index 0aeab8c..6b9f5a4 100644 --- a/src/services/FirebaseService.ts +++ b/src/services/FirebaseService.ts @@ -67,6 +67,7 @@ export default class FirebaseService { interval: ReturnType ) => { try { + console.log("Server status DEAD recorded."); await db.ref("live").set(false); if (interval) clearInterval(interval); } catch (e) { diff --git a/src/utilities/interfaces.ts b/src/utilities/interfaces.ts index 4ce93f1..335e673 100644 --- a/src/utilities/interfaces.ts +++ b/src/utilities/interfaces.ts @@ -101,3 +101,22 @@ export type TorrentsHealth = { webtorrent: TorrentHealth; bittorrent: TorrentHealth; }; + +export interface ServerToClientEvents { + noArg: () => void; + basicEmit: (a: number, b: string, c: Buffer) => void; + withAck: (d: string, callback: (e: number) => void) => void; +} + +export interface ClientToServerEvents { + hello: () => void; +} + +export interface InterServerEvents { + ping: () => void; +} + +export interface SocketData { + name: string; + age: number; +} diff --git a/src/worker/DBWorker/index.ts b/src/worker/DBWorker/index.ts index 6a7fd2b..6cbfdb1 100644 --- a/src/worker/DBWorker/index.ts +++ b/src/worker/DBWorker/index.ts @@ -3,12 +3,10 @@ import DBService from "../Services/DBService"; FirebaseService.attachDBListeners(DBService.listenToRemovalsCB); -process.on("SIGINT", () => { +const shutDownDBWorker = () => { FirebaseService.removeListeners(DBService.listenToRemovalsCB); process.exit(0); -}); +}; -process.on("SIGTERM", () => { - FirebaseService.removeListeners(DBService.listenToRemovalsCB); - process.exit(0); -}); +process.on("SIGINT", shutDownDBWorker); +process.on("SIGTERM", shutDownDBWorker); diff --git a/src/worker/TorrentsWorker/index.ts b/src/worker/TorrentsWorker/index.ts index fff01af..3a88fbf 100644 --- a/src/worker/TorrentsWorker/index.ts +++ b/src/worker/TorrentsWorker/index.ts @@ -99,20 +99,14 @@ worker.on("progress", (job: Job, progress: number) => { console.log(keys.TORRENTS_QUEUE, job.name, progress); }); -process.on("SIGINT", async () => { +const shutDownTorrentsWorker = async () => { await worker.close(true); client.destroy(async (error: Error) => { if (error) console.log(error.message); console.log("WebTorrent client destroyed"); process.exit(0); }); -}); +}; -process.on("SIGTERM", async () => { - await worker.close(true); - client.destroy(async (error: Error) => { - if (error) console.log(error.message); - console.log("WebTorrent client destroyed"); - process.exit(0); - }); -}); +process.on("SIGINT", shutDownTorrentsWorker); +process.on("SIGTERM", shutDownTorrentsWorker); diff --git a/src/worker/index.ts b/src/worker/index.ts index 796fbe8..69c82da 100644 --- a/src/worker/index.ts +++ b/src/worker/index.ts @@ -107,12 +107,10 @@ worker.on("progress", (job: Job, progress: number) => { console.log(keys.MAIN_QUEUE, job.name, job.data.url, progress); }); -process.on("SIGINT", async () => { +const shutDownWorker = async () => { await worker.close(true); process.exit(0); -}); +}; -process.on("SIGTERM", async () => { - await worker.close(true); - process.exit(0); -}); +process.on("SIGINT", shutDownWorker); +process.on("SIGTERM", shutDownWorker);