Merge branch 'main' into feat/logs-python-process-errors

This commit is contained in:
Zamitto
2024-08-06 11:22:47 -03:00
committed by GitHub
44 changed files with 1884 additions and 286 deletions

View File

@@ -43,8 +43,15 @@ import "./auth/sign-out";
import "./auth/open-auth-window";
import "./auth/get-session-hash";
import "./user/get-user";
import "./user/block-user";
import "./user/unblock-user";
import "./user/get-user-friends";
import "./profile/get-friend-requests";
import "./profile/get-me";
import "./profile/undo-friendship";
import "./profile/update-friend-request";
import "./profile/update-profile";
import "./profile/send-friend-request";
ipcMain.handle("ping", () => "pong");
ipcMain.handle("getVersion", () => app.getVersion());

View File

@@ -0,0 +1,11 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
import { FriendRequest } from "@types";
const getFriendRequests = async (
_event: Electron.IpcMainInvokeEvent
): Promise<FriendRequest[]> => {
return HydraApi.get(`/profile/friend-requests`).catch(() => []);
};
registerEvent("getFriendRequests", getFriendRequests);

View File

@@ -9,9 +9,7 @@ const getMe = async (
_event: Electron.IpcMainInvokeEvent
): Promise<UserProfile | null> => {
return HydraApi.get(`/profile/me`)
.then((response) => {
const me = response.data;
.then((me) => {
userAuthRepository.upsert(
{
id: 1,
@@ -26,12 +24,18 @@ const getMe = async (
return me;
})
.catch((err) => {
.catch(async (err) => {
if (err instanceof UserNotLoggedInError) {
return null;
}
return userAuthRepository.findOne({ where: { id: 1 } });
const loggedUser = await userAuthRepository.findOne({ where: { id: 1 } });
if (loggedUser) {
return { ...loggedUser, id: loggedUser.userId };
}
return null;
});
};

View File

@@ -0,0 +1,11 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
const sendFriendRequest = async (
_event: Electron.IpcMainInvokeEvent,
userId: string
) => {
return HydraApi.post("/profile/friend-requests", { friendCode: userId });
};
registerEvent("sendFriendRequest", sendFriendRequest);

View File

@@ -0,0 +1,11 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
const undoFriendship = async (
_event: Electron.IpcMainInvokeEvent,
userId: string
) => {
await HydraApi.delete(`/profile/friends/${userId}`);
};
registerEvent("undoFriendship", undoFriendship);

View File

@@ -0,0 +1,19 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
import { FriendRequestAction } from "@types";
const updateFriendRequest = async (
_event: Electron.IpcMainInvokeEvent,
userId: string,
action: FriendRequestAction
) => {
if (action == "CANCEL") {
return HydraApi.delete(`/profile/friend-requests/${userId}`);
}
return HydraApi.patch(`/profile/friend-requests/${userId}`, {
requestState: action,
});
};
registerEvent("updateFriendRequest", updateFriendRequest);

View File

@@ -26,11 +26,9 @@ const updateProfile = async (
_event: Electron.IpcMainInvokeEvent,
displayName: string,
newProfileImagePath: string | null
) => {
): Promise<UserProfile> => {
if (!newProfileImagePath) {
return patchUserProfile(displayName).then(
(response) => response.data as UserProfile
);
return patchUserProfile(displayName);
}
const stats = fs.statSync(newProfileImagePath);
@@ -42,7 +40,7 @@ const updateProfile = async (
imageLength: fileSizeInBytes,
})
.then(async (preSignedResponse) => {
const { presignedUrl, profileImageUrl } = preSignedResponse.data;
const { presignedUrl, profileImageUrl } = preSignedResponse;
const mimeType = await fileTypeFromFile(newProfileImagePath);
@@ -51,13 +49,11 @@ const updateProfile = async (
"Content-Type": mimeType?.mime,
},
});
return profileImageUrl;
return profileImageUrl as string;
})
.catch(() => undefined);
return patchUserProfile(displayName, profileImageUrl).then(
(response) => response.data as UserProfile
);
return patchUserProfile(displayName, profileImageUrl);
};
registerEvent("updateProfile", updateProfile);

View File

@@ -0,0 +1,11 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
const blockUser = async (
_event: Electron.IpcMainInvokeEvent,
userId: string
) => {
await HydraApi.post(`/user/${userId}/block`);
};
registerEvent("blockUser", blockUser);

View File

@@ -0,0 +1,29 @@
import { userAuthRepository } from "@main/repository";
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
import { UserFriends } from "@types";
export const getUserFriends = async (
userId: string,
take: number,
skip: number
): Promise<UserFriends> => {
const loggedUser = await userAuthRepository.findOne({ where: { id: 1 } });
if (loggedUser?.userId === userId) {
return HydraApi.get(`/profile/friends`, { take, skip });
}
return HydraApi.get(`/user/${userId}/friends`, { take, skip });
};
const getUserFriendsEvent = async (
_event: Electron.IpcMainInvokeEvent,
userId: string,
take: number,
skip: number
) => {
return getUserFriends(userId, take, skip);
};
registerEvent("getUserFriends", getUserFriendsEvent);

View File

@@ -4,14 +4,19 @@ import { steamGamesWorker } from "@main/workers";
import { UserProfile } from "@types";
import { convertSteamGameToCatalogueEntry } from "../helpers/search-games";
import { getSteamAppAsset } from "@main/helpers";
import { getUserFriends } from "./get-user-friends";
const getUser = async (
_event: Electron.IpcMainInvokeEvent,
userId: string
): Promise<UserProfile | null> => {
try {
const response = await HydraApi.get(`/user/${userId}`);
const profile = response.data;
const [profile, friends] = await Promise.all([
HydraApi.get(`/user/${userId}`),
getUserFriends(userId, 12, 0).catch(() => {
return { totalFriends: 0, friends: [] };
}),
]);
const recentGames = await Promise.all(
profile.recentGames.map(async (game) => {
@@ -47,7 +52,13 @@ const getUser = async (
})
);
return { ...profile, libraryGames, recentGames };
return {
...profile,
libraryGames,
recentGames,
friends: friends.friends,
totalFriends: friends.totalFriends,
};
} catch (err) {
return null;
}

View File

@@ -0,0 +1,11 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
const unblockUser = async (
_event: Electron.IpcMainInvokeEvent,
userId: string
) => {
await HydraApi.post(`/user/${userId}/unblock`);
};
registerEvent("unblockUser", unblockUser);

View File

@@ -20,6 +20,8 @@ autoUpdater.setFeedURL({
autoUpdater.logger = logger;
logger.log("Init Hydra");
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) app.quit();
@@ -121,6 +123,7 @@ app.on("window-all-closed", () => {
app.on("before-quit", () => {
/* Disconnects libtorrent */
PythonInstance.kill();
logger.log("Quit Hydra");
});
app.on("activate", () => {

View File

@@ -10,7 +10,7 @@ import { UserNotLoggedInError } from "@shared";
export class HydraApi {
private static instance: AxiosInstance;
private static readonly EXPIRATION_OFFSET_IN_MS = 1000 * 60 * 5;
private static readonly EXPIRATION_OFFSET_IN_MS = 1000 * 60 * 5; // 5 minutes
private static secondsToMilliseconds = (seconds: number) => seconds * 1000;
@@ -45,6 +45,8 @@ export class HydraApi {
expirationTimestamp: tokenExpirationTimestamp,
};
logger.log("Sign in received", this.userAuth);
await userAuthRepository.upsert(
{
id: 1,
@@ -70,11 +72,11 @@ export class HydraApi {
this.instance.interceptors.request.use(
(request) => {
logger.log(" ---- REQUEST -----");
logger.log(request.method, request.url, request.data);
logger.log(request.method, request.url, request.params, request.data);
return request;
},
(error) => {
logger.log("request error", error);
logger.error("request error", error);
return Promise.reject(error);
}
);
@@ -95,12 +97,18 @@ export class HydraApi {
const { config } = error;
logger.error(config.method, config.baseURL, config.url, config.headers);
logger.error(
config.method,
config.baseURL,
config.url,
config.headers,
config.data
);
if (error.response) {
logger.error(error.response.status, error.response.data);
logger.error("Response", error.response.status, error.response.data);
} else if (error.request) {
logger.error(error.request);
logger.error("Request", error.request);
} else {
logger.error("Error", error.message);
}
@@ -146,6 +154,8 @@ export class HydraApi {
this.userAuth.authToken = accessToken;
this.userAuth.expirationTimestamp = tokenExpirationTimestamp;
logger.log("Token refreshed", this.userAuth);
userAuthRepository.upsert(
{
id: 1,
@@ -170,6 +180,8 @@ export class HydraApi {
private static handleUnauthorizedError = (err) => {
if (err instanceof AxiosError && err.response?.status === 401) {
logger.error("401 - Current credentials:", this.userAuth);
this.userAuth = {
authToken: "",
expirationTimestamp: 0,
@@ -184,48 +196,53 @@ export class HydraApi {
throw err;
};
static async get(url: string) {
static async get<T = any>(url: string, params?: any) {
if (!this.isLoggedIn()) throw new UserNotLoggedInError();
await this.revalidateAccessTokenIfExpired();
return this.instance
.get(url, this.getAxiosConfig())
.get<T>(url, { params, ...this.getAxiosConfig() })
.then((response) => response.data)
.catch(this.handleUnauthorizedError);
}
static async post(url: string, data?: any) {
static async post<T = any>(url: string, data?: any) {
if (!this.isLoggedIn()) throw new UserNotLoggedInError();
await this.revalidateAccessTokenIfExpired();
return this.instance
.post(url, data, this.getAxiosConfig())
.post<T>(url, data, this.getAxiosConfig())
.then((response) => response.data)
.catch(this.handleUnauthorizedError);
}
static async put(url: string, data?: any) {
static async put<T = any>(url: string, data?: any) {
if (!this.isLoggedIn()) throw new UserNotLoggedInError();
await this.revalidateAccessTokenIfExpired();
return this.instance
.put(url, data, this.getAxiosConfig())
.put<T>(url, data, this.getAxiosConfig())
.then((response) => response.data)
.catch(this.handleUnauthorizedError);
}
static async patch(url: string, data?: any) {
static async patch<T = any>(url: string, data?: any) {
if (!this.isLoggedIn()) throw new UserNotLoggedInError();
await this.revalidateAccessTokenIfExpired();
return this.instance
.patch(url, data, this.getAxiosConfig())
.patch<T>(url, data, this.getAxiosConfig())
.then((response) => response.data)
.catch(this.handleUnauthorizedError);
}
static async delete(url: string) {
static async delete<T = any>(url: string) {
if (!this.isLoggedIn()) throw new UserNotLoggedInError();
await this.revalidateAccessTokenIfExpired();
return this.instance
.delete(url, this.getAxiosConfig())
.delete<T>(url, this.getAxiosConfig())
.then((response) => response.data)
.catch(this.handleUnauthorizedError);
}
}

View File

@@ -10,11 +10,7 @@ export const createGame = async (game: Game) => {
lastTimePlayed: game.lastTimePlayed,
})
.then((response) => {
const {
id: remoteId,
playTimeInMilliseconds,
lastTimePlayed,
} = response.data;
const { id: remoteId, playTimeInMilliseconds, lastTimePlayed } = response;
gameRepository.update(
{ objectID: game.objectID },

View File

@@ -6,7 +6,7 @@ import { getSteamAppAsset } from "@main/helpers";
export const mergeWithRemoteGames = async () => {
return HydraApi.get("/games")
.then(async (response) => {
for (const game of response.data) {
for (const game of response) {
const localGame = await gameRepository.findOne({
where: {
objectID: game.objectId,