- 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>
173 lines
5.6 KiB
C++
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;
|
|
}
|
|
|
|
}
|