diff --git a/src/interfaces/extendedWebsocket.ts b/src/interfaces/extendedWebsocket.ts index ec9699e..739ce5d 100644 --- a/src/interfaces/extendedWebsocket.ts +++ b/src/interfaces/extendedWebsocket.ts @@ -6,6 +6,6 @@ export interface ExtendedWebSocket extends WebSocket { payload: DecodedToken; isAlive: boolean; user: IUser; - asyncUpdates?: NodeJS.Timeout + asyncUpdates: Map } diff --git a/src/utils/websocket/websocketCustomEvents/getSpotifyUpdatesEvent.ts b/src/utils/websocket/websocketCustomEvents/getSpotifyUpdatesEvent.ts index 2f0bd41..ca768e9 100644 --- a/src/utils/websocket/websocketCustomEvents/getSpotifyUpdatesEvent.ts +++ b/src/utils/websocket/websocketCustomEvents/getSpotifyUpdatesEvent.ts @@ -4,6 +4,8 @@ import {SpotifyTokenService} from "../../../db/services/spotifyTokenService"; import {UserService} from "../../../db/services/db/UserService"; import {getCurrentlyPlaying} from "../../../db/services/spotifyApiService"; +export const SpotifyAsyncUpdateEvent = "SPOTIFY_UPDATE"; + export class GetSpotifyUpdatesEvent extends CustomWebsocketEvent { event = WebsocketEventType.GET_SPOTIFY_UPDATES; @@ -12,9 +14,14 @@ export class GetSpotifyUpdatesEvent extends CustomWebsocketEvent { console.log("Starting Spotify updates"); this.ws.emit(WebsocketEventType.GET_SINGLE_SPOTIFY_UPDATE, {}); - this.ws.asyncUpdates = setInterval(() => { + if (this.ws.asyncUpdates.has(SpotifyAsyncUpdateEvent)) { + console.log("Spotify updates already running"); + return; + } + + this.ws.asyncUpdates.set(SpotifyAsyncUpdateEvent, setInterval(() => { this.ws.emit(WebsocketEventType.GET_SINGLE_SPOTIFY_UPDATE, {}); - }, 1000); + }, 1000)); } } diff --git a/src/utils/websocket/websocketCustomEvents/getWeatherUpdatesEvent.ts b/src/utils/websocket/websocketCustomEvents/getWeatherUpdatesEvent.ts index 9334b4e..92d75f6 100644 --- a/src/utils/websocket/websocketCustomEvents/getWeatherUpdatesEvent.ts +++ b/src/utils/websocket/websocketCustomEvents/getWeatherUpdatesEvent.ts @@ -2,6 +2,8 @@ import {CustomWebsocketEvent} from "./customWebsocketEvent"; import {WebsocketEventType} from "./websocketEventType"; import {getCurrentWeather} from "../../../db/services/owmApiService"; +export const WeatherAsyncUpdateEvent = "WEATHER_UPDATE"; + export class GetWeatherUpdatesEvent extends CustomWebsocketEvent { event = WebsocketEventType.GET_WEATHER_UPDATES; @@ -10,9 +12,16 @@ export class GetWeatherUpdatesEvent extends CustomWebsocketEvent { console.log("Starting weather updates"); this.ws.emit(WebsocketEventType.GET_SINGLE_WEATHER_UPDATE); - this.ws.asyncUpdates = setInterval(() => { + if (this.ws.asyncUpdates.has(WeatherAsyncUpdateEvent)) { + console.log("Weather updates already running"); + return; + } + + this.ws.asyncUpdates.set(WeatherAsyncUpdateEvent, setInterval(() => { this.ws.emit(WebsocketEventType.GET_SINGLE_WEATHER_UPDATE); - }, 1000 * 60); + }, 1000 * 60)); + + } } diff --git a/src/utils/websocket/websocketCustomEvents/stopSpotifyUpdatesEvent.ts b/src/utils/websocket/websocketCustomEvents/stopSpotifyUpdatesEvent.ts index 9b28799..71d20b1 100644 --- a/src/utils/websocket/websocketCustomEvents/stopSpotifyUpdatesEvent.ts +++ b/src/utils/websocket/websocketCustomEvents/stopSpotifyUpdatesEvent.ts @@ -1,13 +1,15 @@ import {CustomWebsocketEvent} from "./customWebsocketEvent"; import {WebsocketEventType} from "./websocketEventType"; +import {SpotifyAsyncUpdateEvent} from "./getSpotifyUpdatesEvent"; export class StopSpotifyUpdatesEvent extends CustomWebsocketEvent { event = WebsocketEventType.STOP_SPOTIFY_UPDATES; handler = async () => { - if (this.ws.asyncUpdates) { - clearInterval(this.ws.asyncUpdates); + if (this.ws.asyncUpdates.has(SpotifyAsyncUpdateEvent)) { + clearInterval(this.ws.asyncUpdates.get(SpotifyAsyncUpdateEvent)); + this.ws.asyncUpdates.delete(SpotifyAsyncUpdateEvent); console.log("Spotify updates stopped"); } } diff --git a/src/utils/websocket/websocketCustomEvents/stopUpdateUserEvent.ts b/src/utils/websocket/websocketCustomEvents/stopUpdateUserEvent.ts new file mode 100644 index 0000000..f317216 --- /dev/null +++ b/src/utils/websocket/websocketCustomEvents/stopUpdateUserEvent.ts @@ -0,0 +1,17 @@ +import {WebsocketEventType} from "./websocketEventType"; +import {CustomWebsocketEvent} from "./customWebsocketEvent"; +import {UserAsyncUpdateEvent} from "./updateUserEvent"; + +export class StopUpdateUserEvent extends CustomWebsocketEvent { + + event = WebsocketEventType.STOP_UPDATE_USER; + + handler = async () => { + if (this.ws.asyncUpdates.has(UserAsyncUpdateEvent)) { + clearInterval(this.ws.asyncUpdates.get(UserAsyncUpdateEvent)); + this.ws.asyncUpdates.delete(UserAsyncUpdateEvent); + console.log("User updates stopped"); + } + } +} + diff --git a/src/utils/websocket/websocketCustomEvents/stopWeatherUpdatesEvent.ts b/src/utils/websocket/websocketCustomEvents/stopWeatherUpdatesEvent.ts index 9d5ca2f..5c29241 100644 --- a/src/utils/websocket/websocketCustomEvents/stopWeatherUpdatesEvent.ts +++ b/src/utils/websocket/websocketCustomEvents/stopWeatherUpdatesEvent.ts @@ -1,16 +1,17 @@ import {CustomWebsocketEvent} from "./customWebsocketEvent"; import {WebsocketEventType} from "./websocketEventType"; +import {WeatherAsyncUpdateEvent} from "./getWeatherUpdatesEvent"; export class StopWeatherUpdatesEvent extends CustomWebsocketEvent { event = WebsocketEventType.STOP_WEATHER_UPDATES; handler = async () => { - if (this.ws.asyncUpdates) { - clearInterval(this.ws.asyncUpdates); + if (this.ws.asyncUpdates.has(WeatherAsyncUpdateEvent)) { + clearInterval(this.ws.asyncUpdates.get(WeatherAsyncUpdateEvent)); + this.ws.asyncUpdates.delete(WeatherAsyncUpdateEvent); console.log("Weather updates stopped"); } } - } diff --git a/src/utils/websocket/websocketCustomEvents/updateUserEvent.ts b/src/utils/websocket/websocketCustomEvents/updateUserEvent.ts index 5c96d1e..e6569d0 100644 --- a/src/utils/websocket/websocketCustomEvents/updateUserEvent.ts +++ b/src/utils/websocket/websocketCustomEvents/updateUserEvent.ts @@ -1,10 +1,32 @@ import {WebsocketEventType} from "./websocketEventType"; import {CustomWebsocketEvent} from "./customWebsocketEvent"; import {IUser} from "../../../db/models/user"; +import {UserService} from "../../../db/services/db/UserService"; + +export const UserAsyncUpdateEvent = "USER_UPDATE"; export class UpdateUserEvent extends CustomWebsocketEvent { event = WebsocketEventType.UPDATE_USER; + handler = async () => { + console.log("Starting user updates") + if (this.ws.asyncUpdates.has(UserAsyncUpdateEvent)) { + console.log("User updates already running"); + return; + } + + this.ws.asyncUpdates.set(UserAsyncUpdateEvent, setInterval(async () => { + const userService = await UserService.create(); + const user = await userService.getUserByUUID(this.ws.payload.uuid); + this.ws.emit(WebsocketEventType.UPDATE_USER_SINGLE, user); + }, 1000 * 15)); + + } +} + +export class UpdateUserSingleEvent extends CustomWebsocketEvent { + event = WebsocketEventType.UPDATE_USER_SINGLE; + handler = async (data: IUser) => { console.log("Updating user") if (data) { diff --git a/src/utils/websocket/websocketCustomEvents/websocketEventType.ts b/src/utils/websocket/websocketCustomEvents/websocketEventType.ts index c39d1fe..4ab68a7 100644 --- a/src/utils/websocket/websocketCustomEvents/websocketEventType.ts +++ b/src/utils/websocket/websocketCustomEvents/websocketEventType.ts @@ -9,4 +9,7 @@ export enum WebsocketEventType { STOP_WEATHER_UPDATES = "STOP_WEATHER_UPDATES", ERROR = "ERROR", UPDATE_USER = "UPDATE_USER", + UPDATE_USER_SINGLE = "UPDATE_USER_SINGLE", + STOP_UPDATE_USER = "STOP_UPDATE_USER", + } diff --git a/src/utils/websocket/websocketCustomEvents/websocketEventUtils.ts b/src/utils/websocket/websocketCustomEvents/websocketEventUtils.ts index 35581f3..9b8d223 100644 --- a/src/utils/websocket/websocketCustomEvents/websocketEventUtils.ts +++ b/src/utils/websocket/websocketCustomEvents/websocketEventUtils.ts @@ -6,8 +6,9 @@ import {GetStateEvent} from "./getStateEvent"; import {GetSingleWeatherUpdateEvent, GetWeatherUpdatesEvent} from "./getWeatherUpdatesEvent"; import {StopSpotifyUpdatesEvent} from "./stopSpotifyUpdatesEvent"; import {StopWeatherUpdatesEvent} from "./stopWeatherUpdatesEvent"; -import {UpdateUserEvent} from "./updateUserEvent"; +import {UpdateUserEvent, UpdateUserSingleEvent} from "./updateUserEvent"; import {CustomWebsocketEvent} from "./customWebsocketEvent"; +import {StopUpdateUserEvent} from "./stopUpdateUserEvent"; export function getEventListeners(ws: ExtendedWebSocket): CustomWebsocketEvent[] { return [ @@ -20,6 +21,8 @@ export function getEventListeners(ws: ExtendedWebSocket): CustomWebsocketEvent[] new GetWeatherUpdatesEvent(ws), new StopWeatherUpdatesEvent(ws), new UpdateUserEvent(ws), + new UpdateUserSingleEvent(ws), + new StopUpdateUserEvent(ws), new ErrorEvent(ws) ]; } diff --git a/src/utils/websocket/websocketEventHandler.ts b/src/utils/websocket/websocketEventHandler.ts index cd7eca0..4e8ff29 100644 --- a/src/utils/websocket/websocketEventHandler.ts +++ b/src/utils/websocket/websocketEventHandler.ts @@ -21,9 +21,9 @@ export class WebsocketEventHandler { this.webSocket.onclose = (event) => { console.log("WebSocket closed:", event.code, event.reason, event.wasClean, event.type); console.log(`User: ${this.webSocket.payload.username} disconnected`); - if (this.webSocket.asyncUpdates) { - clearInterval(this.webSocket.asyncUpdates); - console.log("Async updates stopped"); + for (const [key, value] of this.webSocket.asyncUpdates) { + console.log("Stopping Update:", key); + clearInterval(value); } callback(); }; @@ -42,7 +42,7 @@ export class WebsocketEventHandler { ); } - public registerCustomEvent(customWebsocketEvent:CustomWebsocketEvent ) { + public registerCustomEvent(customWebsocketEvent: CustomWebsocketEvent) { // bind needed? this.webSocket.on(customWebsocketEvent.event, customWebsocketEvent.handler.bind(customWebsocketEvent)); } diff --git a/src/utils/websocket/websocketServerEventHandler.ts b/src/utils/websocket/websocketServerEventHandler.ts index 2d482e4..1b99fa0 100644 --- a/src/utils/websocket/websocketServerEventHandler.ts +++ b/src/utils/websocket/websocketServerEventHandler.ts @@ -26,6 +26,8 @@ export class WebsocketServerEventHandler { // second: set the isAlive flag to true ws.isAlive = true; + ws.asyncUpdates = new Map(); + // last: call the callback function callback(ws, request); }, diff --git a/src/websocket.ts b/src/websocket.ts index 2e22cef..6e46b5d 100644 --- a/src/websocket.ts +++ b/src/websocket.ts @@ -5,7 +5,6 @@ import {ExtendedWebSocket} from "./interfaces/extendedWebsocket"; import {DecodedToken} from "./interfaces/decodedToken"; import {WebsocketServerEventHandler} from "./utils/websocket/websocketServerEventHandler"; import {WebsocketEventHandler} from "./utils/websocket/websocketEventHandler"; -import {UserService} from "./db/services/db/UserService"; import {getEventListeners} from "./utils/websocket/websocketCustomEvents/websocketEventUtils"; import {WebsocketEventType} from "./utils/websocket/websocketCustomEvents/websocketEventType"; @@ -64,15 +63,8 @@ export class ExtendedWebSocketServer { // Register custom events getEventListeners(ws).forEach(socketEventHandler.registerCustomEvent, socketEventHandler); - const updateUserInterval = setInterval(async () => { - const userService = await UserService.create(); - const user = await userService.getUserByUUID(ws.payload.uuid); - ws.emit(WebsocketEventType.UPDATE_USER, user); - }, 15000); - socketEventHandler.enableDisconnectEvent(() => { - clearInterval(updateUserInterval); - console.log("stopped updating user"); + console.log("User disconnected"); }); // send initial state and settings @@ -80,6 +72,9 @@ export class ExtendedWebSocketServer { ws.emit(WebsocketEventType.GET_STATE, {}); ws.emit(WebsocketEventType.GET_SETTINGS, {}); + // initiate update user event + ws.emit(WebsocketEventType.UPDATE_USER, {}); + const mode = ws.user.lastState?.global.mode; if (mode === "clock" && !ws.asyncUpdates) { ws.emit(WebsocketEventType.GET_WEATHER_UPDATES, {})