Memories & Comments
What it is
activity-log owns event "memories" — photo/video uploads guests and planners post to an event, plus reactions and moderation reporting. comment-service provides threaded comments on top of any entity (memories primarily), using the same interestId-scoping pattern as Chat.
Core concepts
- A memory is a specific kind of activity log entry (
type='memory') — activity logs are the broader concept, but memory upload is the one that matters most: it's what feeds the Points system (both host and guest points are earned specifically by memory uploads), and it's the one users interact with via reactions, comments, and reports. getExploreMemoriesis a cross-event public feed (GET /activity-log/explore-memories) — distinct fromgetEventMemorieswhich is scoped to one event's planners/guests (isEventPlannerOrGuest()).- 3 reports auto-deletes a memory. Reporting is community-moderated, not just a flag for manual review — once a memory accumulates 3 unique reporters, it's automatically soft-deleted, no admin action required.
- Comments use the same
entityType-entityKeyinterestIdscoping as chat, but note the delimiter differs: comment-service splits on-, chat splits on:. They're separate implementations of a similar idea, not a shared utility — don't assume aninterestIdstring is interchangeable between the two modules.
How it works
Memories
POST /activity-log/events/:eventId— planner-created activity log entry (not necessarily a memory).- Guest memory upload goes through a dedicated endpoint (see Points for how upload triggers async point issuance via Pub/Sub).
GET /activity-log/events/:eventId/memories— list, accessible to planners or guests of that event.DELETE /activity-log/events/:eventId/memories/:memoryId— same dual planner-or-guest access as listing (likely restricted further to the memory's own uploader at the service layer — verify before assuming any guest can delete any memory).POST .../memories/:memoryId/reactions,POST .../activityId/:activityId/reactions— reactions on memories vs. general activity log entries are separate endpoints, not unified.POST .../memories/:memoryId/report— moderation: a guest or planner flags a memory with areason/description, handled byactivityLogService.reportMemory. Each report increments a unique-reporter count (memory_reportstable, one row per(memoryId, reportedBy)pair, DB-enforced so the same user can't report twice); hitting 3 auto-soft-deletes the memory. The creator gets a push + email notification after every report (1/3, 2/3, then a distinct "removed" notification at 3), not just at the threshold.GET /event/memory-shareable— the picker list for "which event can I post a memory to," segmented intoliveEvents(currently between start/end time) andpastEvents(ended), each independently sorted (soonest-first for live, most-recent-first for past). An event only appears if the caller is its creator, an accepted co-planner, or a guest — upcoming (not yet started) and archived events never appear, even for the creator.GET /activity-log/events/:eventId/seen— read-tracking (which activity log entries this user has already seen), likely backing an unread-count/badge in the client.
The explore feed's relevance sources
GET /activity-log/explore-memories merges up to seven sources into one personalized feed: memories from contact users directly, memories from events created by a contact, memories from events where a contact is an accepted co-planner, the caller's own memories, memories from the caller's own created events, memories from events the caller co-plans, and memories from events the caller attended as a guest (matched by user ID, email, or phone — so it still surfaces events you were invited to before you had an account). keepMemoriesPrivate (see Events & Event Types) is enforced as a filter across all seven sources, not just the contact-based ones — being someone's contact never overrides a private event's access list.
Comments
Standard threaded-comment shape scoped by interestId: GET/POST /:interestId/comments, GET /:interestId/comments/count, GET/POST /:interestId/comments/:commentId/replies (one level of nesting), POST /:interestId/comments/:commentId/like (toggle), DELETE /:interestId/comments/:commentId.
Key business rules & edge cases
- Reactions on a memory and reactions on a general activity log entry go through different endpoints — if you're adding reaction support to a new entity type, check which of the two patterns actually applies rather than assuming one covers both.
- The auto-delete threshold (3 reports) is a fixed constant, not per-event configurable — a small, tightly-knit event group could hit it faster (proportionally) than a large public one; there's no admin override endpoint to un-delete a wrongly-removed memory documented yet, only a soft-delete flag in the database.
- If extending comment-service or chat to share logic, reconcile the
interestIddelimiter difference (-vs:) first — copy-pasting a chatinterestIdinto a comment-service call (or vice versa) will fail to parse.
Related endpoints
GET /v1/activity-log/explore-memories, GET /v1/activity-log/events/{eventId}/memories, POST /v1/activity-log/events/{eventId}/memories/{memoryId}/report, GET /v1/event/memory-shareable, GET /v1/comments/{interestId}/comments, POST /v1/comments/{interestId}/comments. Not yet in the generated OpenAPI spec.
Related code
src/modules/activity-log/activity-log.routes.ts,activity-log.controllers.ts,activity-log-service.tssrc/repositories/activitylog.repository.ts—findExploreMemoriesWithUserDetailssrc/modules/comment-service/comment.routes.ts,comment.controller.ts—parseInterestId- Cross-reference:
src/modules/points/host-points-issuance.service.ts,guest-points-issuance.service.ts— triggered by memory uploads