From 1892877b11ae94386a38ce62702aa6574a1ec73e Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 8 Dec 2025 23:55:50 +0100 Subject: [PATCH] Enhance notification handling by enriching notifications with character names --- backend/services/falukantService.js | 88 +++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/backend/services/falukantService.js b/backend/services/falukantService.js index ba31ce2..9ee4451 100644 --- a/backend/services/falukantService.js +++ b/backend/services/falukantService.js @@ -4200,12 +4200,17 @@ class FalukantService extends BaseService { return undergroundTypes; } + async getNotifications(hashedUserId) { const user = await getFalukantUserOrFail(hashedUserId); const notifications = await Notification.findAll({ where: { userId: user.id, shown: false }, order: [['createdAt', 'DESC']] }); + + // Enrich notifications: parse JSON payloads and resolve character names + await enrichNotificationsWithCharacterNames(notifications); + return notifications; } @@ -4219,6 +4224,9 @@ class FalukantService extends BaseService { offset, limit, }); + + await enrichNotificationsWithCharacterNames(rows); + return { items: rows, total: count, page: Number(page) || 1, size: limit }; } @@ -4524,3 +4532,83 @@ class FalukantService extends BaseService { } export default new FalukantService(); + +// Helper: parse notifications for character references and attach characterName +async function enrichNotificationsWithCharacterNames(notifications) { + if (!Array.isArray(notifications) || notifications.length === 0) return; + + const charIds = new Set(); + + for (const n of notifications) { + // Notification.tr may be either a translation key or a JSON string with params + let parsed = null; + try { + parsed = typeof n.tr === 'string' && n.tr.trim().startsWith('{') ? JSON.parse(n.tr) : null; + } catch (err) { + parsed = null; + } + + // If parsed JSON contains character_id or characterId or character, collect it + if (parsed) { + if (parsed.character_id) charIds.add(parsed.character_id); + if (parsed.characterId) charIds.add(parsed.characterId); + if (parsed.character && typeof parsed.character === 'object' && parsed.character.id) charIds.add(parsed.character.id); + } + + // Also check effects or other fields on the notification row + try { + if (n.effects) { + const eff = typeof n.effects === 'string' && n.effects.trim().startsWith('{') ? JSON.parse(n.effects) : n.effects; + if (Array.isArray(eff)) { + for (const e of eff) { + if (e.character_id) charIds.add(e.character_id); + if (e.characterId) charIds.add(e.characterId); + } + } else if (eff && typeof eff === 'object') { + if (eff.character_id) charIds.add(eff.character_id); + if (eff.characterId) charIds.add(eff.characterId); + } + } + } catch (err) { + // ignore parse errors + } + } + + const ids = Array.from(charIds).filter(Boolean); + if (!ids.length) return; + + // Batch load characters and their display names + const characters = await FalukantCharacter.findAll({ + where: { id: { [Op.in]: ids } }, + include: [ + { model: FalukantPredefineFirstname, as: 'definedFirstName', attributes: ['name'] }, + { model: FalukantPredefineLastname, as: 'definedLastName', attributes: ['name'] } + ], + attributes: ['id'] + }); + + const nameMap = new Map(); + for (const c of characters) { + const first = c.definedFirstName?.name || ''; + const last = c.definedLastName?.name || ''; + const display = `${first} ${last}`.trim() || null; + nameMap.set(c.id, display || `#${c.id}`); + } + + // Attach resolved name to notifications + for (const n of notifications) { + let parsed = null; + try { parsed = typeof n.tr === 'string' && n.tr.trim().startsWith('{') ? JSON.parse(n.tr) : null; } catch (e) { parsed = null; } + let foundId = null; + if (parsed) { + foundId = parsed.character_id || parsed.characterId || (parsed.character && parsed.character.id) || null; + } + if (!foundId && n.character_id) foundId = n.character_id; + if (!foundId && n.characterId) foundId = n.characterId; + + if (foundId && nameMap.has(foundId)) { + // attach property used by frontend + n.characterName = nameMap.get(foundId); + } + } +}