feat: notifications

This commit is contained in:
Zamitto 2024-09-26 14:47:41 -03:00
parent 5c790edb2c
commit c72eefdb77
8 changed files with 81 additions and 17 deletions

View File

@ -226,7 +226,8 @@
"repack_count_one": "{{count}} repack added", "repack_count_one": "{{count}} repack added",
"repack_count_other": "{{count}} repacks added", "repack_count_other": "{{count}} repacks added",
"new_update_available": "Version {{version}} available", "new_update_available": "Version {{version}} available",
"restart_to_install_update": "Restart Hydra to install the update" "restart_to_install_update": "Restart Hydra to install the update",
"game_achievement_unlocked": "{{game}} achievement unlocked"
}, },
"system_tray": { "system_tray": {
"open": "Open Hydra", "open": "Open Hydra",

View File

@ -1,23 +1,30 @@
import type { GameAchievement, GameShop } from "@types"; import type { GameAchievement, GameShop } from "@types";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services"; import { HydraApi } from "@main/services";
import { gameAchievementRepository, gameRepository } from "@main/repository"; import {
gameAchievementRepository,
gameRepository,
userPreferencesRepository,
} from "@main/repository";
const getGameAchievements = async ( const getGameAchievements = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
objectId: string, objectId: string,
shop: GameShop shop: GameShop
): Promise<GameAchievement[]> => { ): Promise<GameAchievement[]> => {
const [game, cachedAchievements] = await Promise.all([ const [game, cachedAchievements, userPreferences] = await Promise.all([
gameRepository.findOne({ gameRepository.findOne({
where: { objectID: objectId, shop }, where: { objectID: objectId, shop },
}), }),
gameAchievementRepository.findOne({ where: { objectId, shop } }), gameAchievementRepository.findOne({ where: { objectId, shop } }),
userPreferencesRepository.findOne({
where: { id: 1 },
}),
]); ]);
const apiAchievement = HydraApi.get( const apiAchievement = HydraApi.get(
"/games/achievements", "/games/achievements",
{ objectId, shop }, { objectId, shop, language: userPreferences?.language || "en" },
{ needsAuth: false } { needsAuth: false }
) )
.then((achievements) => { .then((achievements) => {

View File

@ -16,7 +16,6 @@ import { publishNewRepacksNotifications } from "./services/notifications";
import { MoreThan } from "typeorm"; import { MoreThan } from "typeorm";
import { HydraApi } from "./services/hydra-api"; import { HydraApi } from "./services/hydra-api";
import { uploadGamesBatch } from "./services/library-sync"; import { uploadGamesBatch } from "./services/library-sync";
import { saveAllLocalSteamAchivements } from "./services/achievements/save-all-local-steam-achivements";
const loadState = async (userPreferences: UserPreferences | null) => { const loadState = async (userPreferences: UserPreferences | null) => {
RepacksManager.updateRepacks(); RepacksManager.updateRepacks();

View File

@ -1,11 +1,17 @@
import { gameAchievementRepository } from "@main/repository"; import { gameAchievementRepository, gameRepository } from "@main/repository";
import { UnlockedAchievement } from "./types"; import { UnlockedAchievement } from "./types";
import { publishNewAchievementNotification } from "../notifications";
import { GameShop } from "@types";
export const mergeAchievements = async ( export const mergeAchievements = async (
objectId: string, objectId: string,
shop: string, shop: string,
achievements: UnlockedAchievement[] achievements: UnlockedAchievement[]
) => { ) => {
const game = await gameRepository.findOne({
where: { objectID: objectId, shop: shop as GameShop },
});
const localGameAchievement = await gameAchievementRepository.findOne({ const localGameAchievement = await gameAchievementRepository.findOne({
where: { where: {
objectId, objectId,
@ -17,16 +23,30 @@ export const mergeAchievements = async (
localGameAchievement?.unlockedAchievements || "[]" localGameAchievement?.unlockedAchievements || "[]"
); );
console.log("file achievemets:", achievements);
const newAchievements = achievements.filter((achievement) => { const newAchievements = achievements.filter((achievement) => {
return !unlockedAchievements.some((localAchievement) => { return !unlockedAchievements.some((localAchievement) => {
return localAchievement.name === achievement.name; return localAchievement.name === achievement.name;
}); });
}); });
for (const achievement of newAchievements) {
const completeAchievement = JSON.parse(
localGameAchievement?.achievements || "[]"
).find((steamAchievement) => {
return achievement.name === steamAchievement.name;
});
if (completeAchievement) {
publishNewAchievementNotification(
game?.title || " ",
completeAchievement.displayName,
completeAchievement.icon
);
}
}
const mergedAchievements = unlockedAchievements.concat(newAchievements); const mergedAchievements = unlockedAchievements.concat(newAchievements);
console.log("merged achievemetns", mergedAchievements);
gameAchievementRepository.upsert( gameAchievementRepository.upsert(
{ {
objectId, objectId,

View File

@ -1,4 +1,8 @@
import { gameAchievementRepository, gameRepository } from "@main/repository"; import {
gameAchievementRepository,
gameRepository,
userPreferencesRepository,
} from "@main/repository";
import { steamFindGameAchievementFiles } from "./steam/steam-find-game-achivement-files"; import { steamFindGameAchievementFiles } from "./steam/steam-find-game-achivement-files";
import { parseAchievementFile } from "./util/parseAchievementFile"; import { parseAchievementFile } from "./util/parseAchievementFile";
import { HydraApi } from "@main/services"; import { HydraApi } from "@main/services";
@ -7,6 +11,10 @@ import { mergeAchievements } from "./merge-achievements";
import { UnlockedAchievement } from "./types"; import { UnlockedAchievement } from "./types";
export const saveAllLocalSteamAchivements = async () => { export const saveAllLocalSteamAchivements = async () => {
const userPreferences = await userPreferencesRepository.findOne({
where: { id: 1 },
});
const gameAchievementFiles = steamFindGameAchievementFiles(); const gameAchievementFiles = steamFindGameAchievementFiles();
for (const objectId of Object.keys(gameAchievementFiles)) { for (const objectId of Object.keys(gameAchievementFiles)) {
@ -22,11 +30,12 @@ export const saveAllLocalSteamAchivements = async () => {
if (!game) continue; if (!game) continue;
if (!localAchievements || !localAchievements.achievements) { if (!localAchievements || !localAchievements.achievements) {
HydraApi.get( await HydraApi.get(
"/games/achievements", "/games/achievements",
{ {
shop: "steam", shop: "steam",
objectId, objectId,
language: userPreferences?.language || "en",
}, },
{ needsAuth: false } { needsAuth: false }
) )
@ -50,11 +59,14 @@ export const saveAllLocalSteamAchivements = async () => {
achievementFile.filePath achievementFile.filePath
); );
console.log(achievementFile.filePath); if (localAchievementFile) {
unlockedAchievements.push(
unlockedAchievements.push( ...checkUnlockedAchievements(
...checkUnlockedAchievements(achievementFile.type, localAchievementFile) achievementFile.type,
); localAchievementFile
)
);
}
} }
mergeAchievements(objectId, "steam", unlockedAchievements); mergeAchievements(objectId, "steam", unlockedAchievements);

View File

@ -1,9 +1,12 @@
import { Notification, nativeImage } from "electron"; import { Notification, app, nativeImage } from "electron";
import { t } from "i18next"; import { t } from "i18next";
import { parseICO } from "icojs"; import { parseICO } from "icojs";
import trayIcon from "@resources/tray-icon.png?asset"; import trayIcon from "@resources/tray-icon.png?asset";
import { Game } from "@main/entity"; import { Game } from "@main/entity";
import { gameRepository, userPreferencesRepository } from "@main/repository"; import { gameRepository, userPreferencesRepository } from "@main/repository";
import axios from "axios";
import fs from "node:fs";
import path from "node:path";
const getGameIconNativeImage = async (gameId: number) => { const getGameIconNativeImage = async (gameId: number) => {
try { try {
@ -82,4 +85,26 @@ export const publishNotificationUpdateReadyToInstall = async (
}).show(); }).show();
}; };
export const publishNewAchievementNotification = async (
game: string,
name: string,
icon: string
) => {
const iconName = icon.split("/").pop() || "icon.png";
await axios.get(icon, { responseType: "stream" }).then((response) => {
return response.data.pipe(
fs.createWriteStream(path.join(app.getPath("temp"), iconName))
);
});
new Notification({
title: t("game_achievement_unlocked", {
ns: "notifications",
game,
}),
body: name,
icon: path.join(app.getPath("temp"), iconName),
}).show();
};
export const publishNewFriendRequestNotification = async () => {}; export const publishNewFriendRequestNotification = async () => {};

View File

@ -13,7 +13,6 @@ import type {
UpdateProfileRequest, UpdateProfileRequest,
} from "@types"; } from "@types";
import type { CatalogueCategory } from "@shared"; import type { CatalogueCategory } from "@shared";
import { Game } from "@main/entity";
contextBridge.exposeInMainWorld("electron", { contextBridge.exposeInMainWorld("electron", {
/* Torrenting */ /* Torrenting */

View File

@ -75,6 +75,7 @@ export function Sidebar() {
src={ src={
achievement.unlocked ? achievement.icon : achievement.icongray achievement.unlocked ? achievement.icon : achievement.icongray
} }
alt={achievement.displayName}
/> />
<div> <div>
<p>{achievement.displayName}</p> <p>{achievement.displayName}</p>