event notification update

This commit is contained in:
2026-03-28 21:23:19 -04:00
parent 3bf01cba1f
commit 36e1be8f40

View File

@@ -15,37 +15,32 @@ const router = express.Router();
// Posts a plain system message to each assigned user group's DM channel
// when an event is created or updated.
async function postEventNotification(schema, eventId, actorId, isUpdate) {
async function sendEventMessage(schema, dmGroupId, actorId, content) {
const r = await queryResult(schema,
"INSERT INTO messages (group_id,user_id,content,type) VALUES ($1,$2,$3,'system') RETURNING id",
[dmGroupId, actorId, content]
);
const msg = await queryOne(schema, `
SELECT m.*, u.name AS user_name, u.display_name AS user_display_name,
u.avatar AS user_avatar, u.role AS user_role, u.status AS user_status,
u.hide_admin_tag AS user_hide_admin_tag, u.about_me AS user_about_me, u.allow_dm AS user_allow_dm
FROM messages m JOIN users u ON m.user_id = u.id WHERE m.id = $1
`, [r.rows[0].id]);
if (msg) { msg.reactions = []; io.to(R(schema, 'group', dmGroupId)).emit('message:new', msg); }
}
async function postEventNotification(schema, eventId, actorId) {
try {
const event = await queryOne(schema, 'SELECT * FROM events WHERE id=$1', [eventId]);
if (!event) return;
const dateStr = new Date(event.start_at).toLocaleDateString('en-US', {
weekday: 'short', month: 'short', day: 'numeric',
});
const verb = isUpdate ? 'updated' : 'added';
const content = `📅 Event ${verb}: "${event.title}" on ${dateStr}`;
const dateStr = new Date(event.start_at).toLocaleDateString('en-US', { weekday:'short', month:'short', day:'numeric' });
const groups = await query(schema, `
SELECT ug.dm_group_id
FROM event_user_groups eug
SELECT ug.dm_group_id FROM event_user_groups eug
JOIN user_groups ug ON ug.id = eug.user_group_id
WHERE eug.event_id = $1 AND ug.dm_group_id IS NOT NULL
`, [eventId]);
for (const { dm_group_id } of groups) {
const r = await queryResult(schema,
"INSERT INTO messages (group_id,user_id,content,type) VALUES ($1,$2,$3,'system') RETURNING id",
[dm_group_id, actorId, content]
);
const msg = await queryOne(schema, `
SELECT m.*, u.name AS user_name, u.display_name AS user_display_name,
u.avatar AS user_avatar, u.role AS user_role, u.status AS user_status,
u.hide_admin_tag AS user_hide_admin_tag, u.about_me AS user_about_me, u.allow_dm AS user_allow_dm
FROM messages m JOIN users u ON m.user_id = u.id WHERE m.id = $1
`, [r.rows[0].id]);
if (msg) { msg.reactions = []; io.to(R(schema, 'group', dm_group_id)).emit('message:new', msg); }
}
for (const { dm_group_id } of groups)
await sendEventMessage(schema, dm_group_id, actorId, `📅 Event added: "${event.title}" on ${dateStr}`);
} catch (e) {
console.error('[Schedule] postEventNotification error:', e.message);
}
@@ -291,7 +286,7 @@ router.post('/', authMiddleware, async (req, res) => {
for (const ugId of groupIds)
await exec(req.schema, 'INSERT INTO event_user_groups (event_id,user_group_id) VALUES ($1,$2) ON CONFLICT DO NOTHING', [eventId, ugId]);
if (groupIds.length > 0)
await postEventNotification(req.schema, eventId, req.user.id, false);
await postEventNotification(req.schema, eventId, req.user.id);
const event = await queryOne(req.schema, 'SELECT * FROM events WHERE id=$1', [eventId]);
res.json({ event: await enrichEvent(req.schema, event) });
} catch (e) { res.status(500).json({ error: e.message }); }
@@ -317,6 +312,14 @@ router.patch('/:id', authMiddleware, async (req, res) => {
}
const fields = { title, eventTypeId, startAt, endAt, allDay, location, description, isPublic, trackAvailability, recurrenceRule, origEvent: event };
// Capture group/DM mapping before applyEventUpdate modifies event_user_groups
const prevGroupRows = await query(req.schema, `
SELECT eug.user_group_id, ug.dm_group_id FROM event_user_groups eug
JOIN user_groups ug ON ug.id=eug.user_group_id
WHERE eug.event_id=$1 AND ug.dm_group_id IS NOT NULL
`, [req.params.id]);
const prevGroupIdSet = new Set(prevGroupRows.map(r => r.user_group_id));
await applyEventUpdate(req.schema, req.params.id, fields, userGroupIds);
// Recurring future scope — update this and all future occurrences
@@ -356,9 +359,47 @@ router.patch('/:id', authMiddleware, async (req, res) => {
}
const updated = await queryOne(req.schema, 'SELECT * FROM events WHERE id=$1', [req.params.id]);
const finalGroups = await query(req.schema, 'SELECT user_group_id FROM event_user_groups WHERE event_id=$1', [req.params.id]);
if (finalGroups.length > 0)
await postEventNotification(req.schema, req.params.id, req.user.id, true);
// Targeted notifications — only for meaningful changes, only to relevant groups
try {
const finalGroupRows = await query(req.schema, `
SELECT eug.user_group_id, ug.dm_group_id FROM event_user_groups eug
JOIN user_groups ug ON ug.id=eug.user_group_id
WHERE eug.event_id=$1 AND ug.dm_group_id IS NOT NULL
`, [req.params.id]);
const allDmIds = finalGroupRows.map(r => r.dm_group_id);
const dateStr = new Date(updated.start_at).toLocaleDateString('en-US', { weekday:'short', month:'short', day:'numeric' });
// Newly added groups → "Event added" only to those groups
if (Array.isArray(userGroupIds)) {
for (const { user_group_id, dm_group_id } of finalGroupRows) {
if (!prevGroupIdSet.has(user_group_id))
await sendEventMessage(req.schema, dm_group_id, req.user.id, `📅 Event added: "${updated.title}" on ${dateStr}`);
}
}
// Date/time changed → "Event updated" to all groups
const timeChanged = (startAt && new Date(startAt).getTime() !== new Date(event.start_at).getTime())
|| (endAt && new Date(endAt).getTime() !== new Date(event.end_at).getTime())
|| (allDay !== undefined && !!allDay !== !!event.all_day);
if (timeChanged) {
for (const dmId of allDmIds)
await sendEventMessage(req.schema, dmId, req.user.id, `📅 Event updated: "${updated.title}" on ${dateStr}`);
}
// Location changed → "Location updated" to all groups
const locationChanged = location !== undefined && (location || null) !== (event.location || null);
if (locationChanged) {
const locContent = updated.location
? `📍 Location updated to "${updated.location}": "${updated.title}" on ${dateStr}`
: `📍 Location removed: "${updated.title}" on ${dateStr}`;
for (const dmId of allDmIds)
await sendEventMessage(req.schema, dmId, req.user.id, locContent);
}
} catch (e) {
console.error('[Schedule] event update notification error:', e.message);
}
res.json({ event: await enrichEvent(req.schema, updated) });
} catch (e) { res.status(500).json({ error: e.message }); }
});