213 lines
6.7 KiB
JavaScript
213 lines
6.7 KiB
JavaScript
// ENVIRONMENT
|
|
require('dotenv').config();
|
|
|
|
// DATABASE
|
|
const { PrismaClient: CMSClient, ActivityType } = require("../../prisma/clients/cms");
|
|
|
|
const prisma = new CMSClient();
|
|
|
|
// RESPONSES
|
|
const { badRequestResponse } = require("../res/responses.js");
|
|
const { successResponse } = require("../res/responses.js");
|
|
|
|
// SERVICES
|
|
const { localTime } = require("../services/time.services.js");
|
|
const logger = require("../services/logger.services.js");
|
|
|
|
const {
|
|
manualTriggerNotification,
|
|
processActivitiesAndSendNotifications,
|
|
analyzeUserActivitiesForNotification,
|
|
updateDailyAnalytics,
|
|
getAINotificationAnalytics
|
|
} = require("../services/notification.services.js");
|
|
|
|
|
|
// CONTROLLER
|
|
exports.create = async (req, res) => {
|
|
try {
|
|
const { userID, activityType, params } = req.body;
|
|
|
|
if (!userID || !activityType || !params) {
|
|
throw new Error("Invalid user ID, activity type, or params!");
|
|
}
|
|
|
|
if (!Object.values(ActivityType).includes(activityType)) {
|
|
throw new Error(`Invalid activity type value, allowed values: ${Object.values(ActivityType).join(", ")}`);
|
|
}
|
|
|
|
const userToken = await prisma.usersToken.findUnique({
|
|
where: { UserID_UT: userID }
|
|
});
|
|
|
|
if (!userToken) {
|
|
throw new Error(`User token not found for userID: ${userID}. Please register user token first.`);
|
|
}
|
|
|
|
let parsedParams = params;
|
|
if (typeof params === 'string' && params.startsWith('{')) {
|
|
try {
|
|
parsedParams = params;
|
|
} catch (e) {
|
|
parsedParams = params;
|
|
}
|
|
}
|
|
|
|
const activity = await prisma.usersActivity.create({
|
|
data: {
|
|
UUID_UT: userToken.UUID_UT,
|
|
ActivityType_UA: activityType,
|
|
Params_UA: parsedParams,
|
|
NotifyAt_UA: localTime(new Date(Date.now() + 1000 * 60 * 5)),
|
|
CreatedAt_UA: localTime(new Date()),
|
|
UpdatedAt_UA: localTime(new Date())
|
|
}
|
|
});
|
|
|
|
return successResponse(res, "User activity created successfully!", {
|
|
activityID: activity.UUID_UA,
|
|
userID: userID,
|
|
activityType: activity.ActivityType_UA,
|
|
createdAt: activity.CreatedAt_UA,
|
|
willTriggerAIAnalysis: true
|
|
});
|
|
|
|
} catch (err) {
|
|
return badRequestResponse(res, "Error creating user activity", err);
|
|
}
|
|
}
|
|
|
|
exports.triggerNotificationForUser = async (req, res) => {
|
|
try {
|
|
const { userID, timeRangeMinutes = 60 } = req.body;
|
|
|
|
if (!userID) {
|
|
throw new Error("userID is required");
|
|
}
|
|
|
|
const result = await manualTriggerNotification(userID, timeRangeMinutes);
|
|
|
|
if (result.success) {
|
|
return successResponse(res, "Notification sent successfully!", result);
|
|
} else {
|
|
return badRequestResponse(res, `Failed to send notification: ${result.reason || result.error}`, result);
|
|
}
|
|
|
|
} catch (err) {
|
|
logger.error("Error triggering notification", { error: err.message, stack: err.stack });
|
|
return badRequestResponse(res, "Error triggering notification", err);
|
|
}
|
|
}
|
|
|
|
exports.analyzeUserActivities = async (req, res) => {
|
|
try {
|
|
const { userID, timeRangeMinutes = 60 } = req.body;
|
|
|
|
if (!userID) {
|
|
throw new Error("userID is required");
|
|
}
|
|
|
|
const analysis = await analyzeUserActivitiesForNotification(userID, timeRangeMinutes);
|
|
|
|
return successResponse(res, "Activity analysis completed", analysis);
|
|
|
|
} catch (err) {
|
|
return badRequestResponse(res, "Error analyzing activities", err);
|
|
}
|
|
}
|
|
|
|
exports.processAllActivitiesAndNotifications = async (req, res) => {
|
|
try {
|
|
const { timeRangeMinutes = 30, minActivityCount = 1 } = req.body;
|
|
|
|
const result = await processActivitiesAndSendNotifications({
|
|
timeRangeMinutes,
|
|
minActivityCount
|
|
});
|
|
|
|
if (result.notificationsSent > 0) {
|
|
try {
|
|
await updateDailyAnalytics();
|
|
result.analyticsUpdated = true;
|
|
} catch (analyticsErr) {
|
|
result.analyticsUpdated = false;
|
|
}
|
|
}
|
|
|
|
return successResponse(res, "Activity processing completed", {
|
|
...result,
|
|
message: `Processed ${result.totalUsersProcessed} users, sent ${result.notificationsSent} AI notifications`
|
|
});
|
|
|
|
} catch (err) {
|
|
return badRequestResponse(res, "Error processing activities", err);
|
|
}
|
|
}
|
|
|
|
exports.getAIInsights = async (req, res) => {
|
|
try {
|
|
const { userID, timeRange = 30 } = req.query;
|
|
|
|
// Get AI notification analytics
|
|
const analytics = await getAINotificationAnalytics({
|
|
startDate: new Date(Date.now() - timeRange * 24 * 60 * 60 * 1000),
|
|
endDate: new Date(),
|
|
limit: 50
|
|
});
|
|
|
|
let userSpecificData = null;
|
|
if (userID) {
|
|
// Get user-specific AI notifications
|
|
userSpecificData = await prisma.aINotification.findMany({
|
|
where: {
|
|
UserID_AIN: userID,
|
|
CreatedAt_AIN: {
|
|
gte: new Date(Date.now() - timeRange * 24 * 60 * 60 * 1000)
|
|
}
|
|
},
|
|
orderBy: {
|
|
CreatedAt_AIN: 'desc'
|
|
},
|
|
take: 10
|
|
});
|
|
|
|
// Get user's recent activities
|
|
const userToken = await prisma.usersToken.findFirst({
|
|
where: { UserID_UT: userID }
|
|
});
|
|
|
|
if (userToken) {
|
|
userSpecificData = {
|
|
notifications: userSpecificData,
|
|
recentActivities: await prisma.usersActivity.findMany({
|
|
where: {
|
|
UUID_UT: userToken.UUID_UT,
|
|
CreatedAt_UA: {
|
|
gte: new Date(Date.now() - 24 * 60 * 60 * 1000) // Last 24 hours
|
|
}
|
|
},
|
|
orderBy: {
|
|
CreatedAt_UA: 'desc'
|
|
},
|
|
take: 20
|
|
})
|
|
};
|
|
}
|
|
}
|
|
|
|
return successResponse(res, "AI insights retrieved successfully!", {
|
|
analytics: analytics.summary,
|
|
userSpecificData,
|
|
integrationStatus: {
|
|
aiNotificationsEnabled: true,
|
|
analyticsTracking: true,
|
|
activityMonitoring: true
|
|
}
|
|
});
|
|
|
|
} catch (err) {
|
|
return badRequestResponse(res, "Error retrieving AI insights", err);
|
|
}
|
|
}
|
|
|