mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-10 05:16:19 +00:00
ci: adding sonar ignore
This commit is contained in:
1
sonar-project.properties
Normal file
1
sonar-project.properties
Normal file
@@ -0,0 +1 @@
|
|||||||
|
sonar.exclusions=src/main/generated/**
|
||||||
17
src/main/services/ws/events/friend-game-session.ts
Normal file
17
src/main/services/ws/events/friend-game-session.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import type { FriendGameSession } from "@main/generated/envelope";
|
||||||
|
import { HydraApi } from "@main/services/hydra-api";
|
||||||
|
import { publishFriendStartedPlayingGameNotification } from "@main/services/notifications";
|
||||||
|
import { GameStats } from "@types";
|
||||||
|
|
||||||
|
export const friendGameSessionEvent = async (payload: FriendGameSession) => {
|
||||||
|
const [friend, gameStats] = await Promise.all([
|
||||||
|
HydraApi.get(`/users/${payload.friendId}`),
|
||||||
|
HydraApi.get<GameStats>(
|
||||||
|
`/games/stats?objectId=${payload.objectId}&shop=steam`
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (friend && gameStats) {
|
||||||
|
publishFriendStartedPlayingGameNotification(friend, gameStats);
|
||||||
|
}
|
||||||
|
};
|
||||||
16
src/main/services/ws/events/friend-request.ts
Normal file
16
src/main/services/ws/events/friend-request.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import type { FriendRequest } from "@main/generated/envelope";
|
||||||
|
import { HydraApi } from "@main/services/hydra-api";
|
||||||
|
import { publishNewFriendRequestNotification } from "@main/services/notifications";
|
||||||
|
import { WindowManager } from "@main/services/window-manager";
|
||||||
|
|
||||||
|
export const friendRequestEvent = async (payload: FriendRequest) => {
|
||||||
|
WindowManager.mainWindow?.webContents.send("on-sync-friend-requests", {
|
||||||
|
friendRequestCount: payload.friendRequestCount,
|
||||||
|
});
|
||||||
|
|
||||||
|
const user = await HydraApi.get(`/users/${payload.senderId}`);
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
publishNewFriendRequestNotification(user);
|
||||||
|
}
|
||||||
|
};
|
||||||
1
src/main/services/ws/index.ts
Normal file
1
src/main/services/ws/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from "./ws-client";
|
||||||
119
src/main/services/ws/ws-client.ts
Normal file
119
src/main/services/ws/ws-client.ts
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import { WebSocket } from "ws";
|
||||||
|
import { HydraApi } from "../hydra-api";
|
||||||
|
import { Envelope } from "@main/generated/envelope";
|
||||||
|
import { logger } from "../logger";
|
||||||
|
import { friendRequestEvent } from "./events/friend-request";
|
||||||
|
import { friendGameSessionEvent } from "./events/friend-game-session";
|
||||||
|
|
||||||
|
export class WSClient {
|
||||||
|
private static ws: WebSocket | null = null;
|
||||||
|
private static reconnectInterval = 1_000;
|
||||||
|
private static readonly maxReconnectInterval = 30_000;
|
||||||
|
private static shouldReconnect = true;
|
||||||
|
private static reconnecting = false;
|
||||||
|
private static heartbeatInterval: NodeJS.Timeout | null = null;
|
||||||
|
|
||||||
|
static async connect() {
|
||||||
|
this.shouldReconnect = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { token } = await HydraApi.post<{ token: string }>("/auth/ws");
|
||||||
|
|
||||||
|
this.ws = new WebSocket(import.meta.env.MAIN_VITE_WS_URL, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
this.ws.on("open", () => {
|
||||||
|
logger.info("WS connected");
|
||||||
|
this.reconnectInterval = 1000;
|
||||||
|
this.reconnecting = false;
|
||||||
|
|
||||||
|
this.startHeartbeat();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.ws.on("message", (message) => {
|
||||||
|
const envelope = Envelope.fromBinary(
|
||||||
|
new Uint8Array(Buffer.from(message.toString()))
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.info("Received WS envelope:", envelope);
|
||||||
|
|
||||||
|
if (envelope.payload.oneofKind === "friendRequest") {
|
||||||
|
friendRequestEvent(envelope.payload.friendRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (envelope.payload.oneofKind === "friendGameSession") {
|
||||||
|
friendGameSessionEvent(envelope.payload.friendGameSession);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.ws.on("close", () => this.handleDisconnect("close"));
|
||||||
|
this.ws.on("error", (err) => {
|
||||||
|
logger.error("WS error:", err);
|
||||||
|
this.handleDisconnect("error");
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
logger.error("Failed to connect WS:", err);
|
||||||
|
this.handleDisconnect("auth-failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static handleDisconnect(reason: string) {
|
||||||
|
logger.warn(`WS disconnected due to ${reason}`);
|
||||||
|
|
||||||
|
if (this.shouldReconnect) {
|
||||||
|
this.cleanupSocket();
|
||||||
|
this.tryReconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async tryReconnect() {
|
||||||
|
if (this.reconnecting) return;
|
||||||
|
this.reconnecting = true;
|
||||||
|
|
||||||
|
logger.info(`Reconnecting in ${this.reconnectInterval / 1000}s...`);
|
||||||
|
|
||||||
|
setTimeout(async () => {
|
||||||
|
try {
|
||||||
|
await this.connect();
|
||||||
|
} catch (err) {
|
||||||
|
logger.error("Reconnect failed:", err);
|
||||||
|
this.reconnectInterval = Math.min(
|
||||||
|
this.reconnectInterval * 2,
|
||||||
|
this.maxReconnectInterval
|
||||||
|
);
|
||||||
|
this.reconnecting = false;
|
||||||
|
this.tryReconnect();
|
||||||
|
}
|
||||||
|
}, this.reconnectInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static cleanupSocket() {
|
||||||
|
if (this.ws) {
|
||||||
|
this.ws.removeAllListeners();
|
||||||
|
this.ws.close();
|
||||||
|
this.ws = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.heartbeatInterval) {
|
||||||
|
clearInterval(this.heartbeatInterval);
|
||||||
|
this.heartbeatInterval = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static close() {
|
||||||
|
this.shouldReconnect = false;
|
||||||
|
this.reconnecting = false;
|
||||||
|
this.cleanupSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static startHeartbeat() {
|
||||||
|
this.heartbeatInterval = setInterval(() => {
|
||||||
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
||||||
|
this.ws.ping();
|
||||||
|
}
|
||||||
|
}, 15_000);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user