aissia/src/modules/NotificationModule.cpp
StillHammer 80f26aea54 Add infrastructure foundation and intelligent document retrieval
- CMakeLists.txt: build configuration
- src/: initial infrastructure structure
- config/: application configuration
- external/: third-party dependencies
- docs/GROVEENGINE_GUIDE.md: GroveEngine reference guide
- docs/architecture/intelligent-document-retrieval.md: agentic retrieval for AIAssistantModule

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:34:16 +08:00

173 lines
5.6 KiB
C++

#include "NotificationModule.h"
#include <grove/JsonDataNode.h>
namespace aissia {
NotificationModule::NotificationModule() {
m_logger = spdlog::get("NotificationModule");
if (!m_logger) {
m_logger = spdlog::stdout_color_mt("NotificationModule");
}
m_config = std::make_unique<grove::JsonDataNode>("config");
}
void NotificationModule::setConfiguration(const grove::IDataNode& configNode,
grove::IIO* io,
grove::ITaskScheduler* scheduler) {
m_io = io;
m_config = std::make_unique<grove::JsonDataNode>("config");
// Charger la configuration
m_language = configNode.getString("language", "fr");
m_silentMode = configNode.getBool("silentMode", false);
m_ttsEnabled = configNode.getBool("ttsEnabled", false);
m_maxQueueSize = configNode.getInt("maxQueueSize", 50);
m_logger->info("NotificationModule configuré: langue={}, silent={}, tts={}",
m_language, m_silentMode, m_ttsEnabled);
}
const grove::IDataNode& NotificationModule::getConfiguration() {
return *m_config;
}
void NotificationModule::process(const grove::IDataNode& input) {
// Traiter la file de notifications
processNotificationQueue();
}
void NotificationModule::notify(const std::string& title, const std::string& message, Priority priority) {
if (m_silentMode && priority != Priority::URGENT) {
return; // Ignorer les notifications non-urgentes en mode silencieux
}
Notification notif;
notif.id = std::to_string(++m_notificationCount);
notif.title = title;
notif.message = message;
notif.priority = priority;
notif.language = m_language;
notif.read = false;
notif.timestamp = 0; // Sera mis à jour lors du process
// Limiter la taille de la queue
while (static_cast<int>(m_pendingNotifications.size()) >= m_maxQueueSize) {
m_pendingNotifications.pop();
}
m_pendingNotifications.push(notif);
if (priority == Priority::URGENT) {
m_urgentCount++;
}
}
void NotificationModule::processNotificationQueue() {
// Traiter jusqu'à 3 notifications par frame pour éviter le spam
int processed = 0;
while (!m_pendingNotifications.empty() && processed < 3) {
Notification notif = m_pendingNotifications.front();
m_pendingNotifications.pop();
displayNotification(notif);
processed++;
}
}
void NotificationModule::displayNotification(const Notification& notif) {
std::string emoji = priorityToEmoji(notif.priority);
std::string priorityStr = priorityToString(notif.priority);
// Affichage console (sera remplacé par Windows toast + TTS)
switch (notif.priority) {
case Priority::URGENT:
m_logger->warn("{} [{}] {}: {}", emoji, priorityStr, notif.title, notif.message);
break;
case Priority::HIGH:
m_logger->info("{} [{}] {}: {}", emoji, priorityStr, notif.title, notif.message);
break;
case Priority::NORMAL:
m_logger->info("{} {}: {}", emoji, notif.title, notif.message);
break;
case Priority::LOW:
m_logger->debug("{} {}: {}", emoji, notif.title, notif.message);
break;
}
// TODO: Intégrer Windows Toast notifications
// TODO: Intégrer TTS si m_ttsEnabled
}
std::string NotificationModule::priorityToString(Priority p) {
switch (p) {
case Priority::LOW: return "INFO";
case Priority::NORMAL: return "RAPPEL";
case Priority::HIGH: return "IMPORTANT";
case Priority::URGENT: return "URGENT";
default: return "?";
}
}
std::string NotificationModule::priorityToEmoji(Priority p) {
switch (p) {
case Priority::LOW: return "[i]";
case Priority::NORMAL: return "[*]";
case Priority::HIGH: return "[!]";
case Priority::URGENT: return "[!!!]";
default: return "[ ]";
}
}
std::unique_ptr<grove::IDataNode> NotificationModule::getHealthStatus() {
auto status = std::make_unique<grove::JsonDataNode>("status");
status->setString("status", "running");
status->setInt("pendingCount", m_pendingNotifications.size());
status->setInt("totalNotifications", m_notificationCount);
status->setInt("urgentCount", m_urgentCount);
status->setBool("silentMode", m_silentMode);
return status;
}
void NotificationModule::shutdown() {
// Vider la queue avant arrêt
while (!m_pendingNotifications.empty()) {
displayNotification(m_pendingNotifications.front());
m_pendingNotifications.pop();
}
m_logger->info("NotificationModule arrêté. Total: {} notifications ({} urgentes)",
m_notificationCount, m_urgentCount);
}
std::unique_ptr<grove::IDataNode> NotificationModule::getState() {
auto state = std::make_unique<grove::JsonDataNode>("state");
state->setInt("notificationCount", m_notificationCount);
state->setInt("urgentCount", m_urgentCount);
state->setInt("pendingCount", m_pendingNotifications.size());
m_logger->debug("État sauvegardé: {} notifications", m_notificationCount);
return state;
}
void NotificationModule::setState(const grove::IDataNode& state) {
m_notificationCount = state.getInt("notificationCount", 0);
m_urgentCount = state.getInt("urgentCount", 0);
// Note: On ne restaure pas la queue - les notifications en attente sont perdues au reload
m_logger->info("État restauré: {} notifications historiques", m_notificationCount);
}
} // namespace aissia
extern "C" {
grove::IModule* createModule() {
return new aissia::NotificationModule();
}
void destroyModule(grove::IModule* module) {
delete module;
}
}