Feature: Forum & Social Engagement
Relevant source files
The following files were used as context for generating this wiki page:- apps/backend/src/forum_module/forum.controller.ts
- apps/backend/src/forum_module/forum.service.ts
- apps/backend/src/forum_module/forum.module.ts
- apps/backend/src/forum_module/entities/thread.entity.ts
- apps/backend/src/forum_module/entities/post.entity.ts
- apps/backend/src/forum_module/entities/reply.entity.ts
- apps/backend/src/social-engagement-module/social-engagement/social-engagement.controller.ts
- apps/backend/src/social-engagement-module/social-engagement/social-engagement.service.ts
- apps/backend/src/social-engagement-module/social-engagement/entities/social-engagement.entity.ts
- apps/backend/src/social-engagement-module/social-engagement/entities/engagement-counter.entity.ts
The Forum and Social Engagement features provide the core community interaction layer for the OnChain Sage application. The Forum module enables users to create discussion threads, post replies, and engage in conversations, typically associated with specific trading signals. It includes mechanisms for content moderation, such as reporting and spam filtering.
The Social Engagement module offers a more lightweight interaction system, allowing users to "like" or "dislike" various types of content polymorphically. This system provides quick feedback and tracks engagement metrics for different content items across the platform. Together, these modules foster a collaborative environment where users can discuss, validate, and react to trading insights.
Forum Module
The Forum Module is a traditional discussion board system built within the NestJS backend. It manages threads, posts, replies, and user interactions like reactions and reports.
Sources: apps/backend/src/forum_module/forum.module.ts, apps/backend/src/forum_module/forum.controller.ts, apps/backend/src/forum_module/forum.service.ts
Architecture and Components
The module is structured using standard NestJS patterns, with a clear separation of concerns between the controller, service, and data layers.
ForumController: Exposes the forum's functionality via a REST API. It handles incoming HTTP requests, validates data using DTOs, and delegates business logic to theForumService.ForumService: Contains the core business logic for all forum operations, such as creating threads, posting replies, and managing reports. It interacts with the database via TypeORM repositories.SpamFilterService: A utility service used byForumServiceto check content for spam before it is saved to the database.- TypeORM Entities: A set of entities (
Thread,Post,Reply,Report,Reaction) that define the database schema and relationships for the forum.
Sources: apps/backend/src/forum_module/forum.controller.ts:16-19, apps/backend/src/forum_module/forum.service.ts:24-34, apps/backend/src/forum_module/forum.module.ts:13-16
The following diagram illustrates the component interactions within the Forum Module.
Data Model
The forum's data is structured around threads, which contain posts. Posts can be either the initial post of a thread or a reply to another post.
This Entity-Relationship diagram shows the database schema for the Forum Module.
Thread Entity
Represents a discussion thread, typically linked to a signalId.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (UUID). |
signalId | string | The ID of the signal this thread is about. |
title | string | The title of the thread. |
authorId | string | The ID of the user who created the thread. |
posts | Post[] | A one-to-many relation to the posts in the thread. |
Sources: apps/backend/src/forum_module/entities/thread.entity.ts:10-31
Post Entity
Represents a single post within a thread.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (UUID). |
content | string | The text content of the post. |
authorId | string | The ID of the user who created the post. |
thread | Thread | A many-to-one relation to the parent thread. |
replies | Reply[] | A one-to-many relation to replies to this post. |
Sources: apps/backend/src/forum_module/entities/post.entity.ts:12-32
Core Functionality
Creating a Thread
A user can create a new thread, which is associated with a signalId. The content is first checked for spam before a new Thread and its initial Post are created and saved.
The sequence diagram below shows the process of creating a new thread.
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /threads/:signalId | Creates a new discussion thread for a signal. |
POST | /threads/:threadId/replies | Adds a reply to a specific thread. |
POST | /posts/:postId/report | Reports a post for moderation. |
GET | /reports | Lists all reported posts (admin only). |
POST | /posts/:postId/react | Adds a reaction to a post. |
GET | /threads | Retrieves all threads. |
GET | /threads/:id | Retrieves a single thread by its ID. |
Sources: apps/backend/src/forum_module/forum.controller.ts:32-108
Social Engagement Module
This module provides a generic system for users to engage with different types of content (e.g., posts, signals, articles) through "likes" and "dislikes". It is designed to be polymorphic, referencing content by a composite key of contentId and contentType.
Sources: apps/backend/src/social-engagement-module/social-engagement/social-engagement.service.ts, apps/backend/src/social-engagement-module/social-engagement/social-engagement.controller.ts
Data Model
The engagement system uses two main entities: SocialEngagement to record individual user actions and EngagementCounter to maintain aggregated counts for fast retrieval.
This ER diagram shows the relationships for the Social Engagement module.
SocialEngagement Entity
Records a single engagement action by a user on a piece of content.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (UUID). |
userId | string | The ID of the user performing the action. |
contentId | string | The ID of the content being engaged with. |
contentType | ContentType | The type of content (e.g., 'POST', 'ARTICLE'). |
engagementType | EngagementType | The type of engagement (e.g., 'LIKE', 'DISLIKE'). |
EngagementCounter Entity
Stores the aggregated like/dislike counts for a piece of content to avoid expensive queries.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (UUID). |
contentId | string | The ID of the content item. |
contentType | ContentType | The type of the content item. |
likes | number | The total number of likes. |
dislikes | number | The total number of dislikes. |
Core Functionality
Creating or Toggling an Engagement
When a user engages with content, the service checks if a previous engagement exists.
- If the new engagement is the same as the old one, it's treated as a removal (e.g., un-liking).
- If it's different (e.g., changing a like to a dislike), the old one is removed and the new one is created.
- If no prior engagement exists, the new one is created.
In all cases, theEngagementCounteris updated atomically.
The following sequence diagram illustrates the logic for creating or toggling an engagement.
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | / | Create or toggle a like/dislike engagement. |
DELETE | /:id | Remove an engagement. |
GET | /user/:contentId/:contentType | Get the current user's engagement for a content item. |
GET | /count/:contentId/:contentType | Get the like/dislike counts for a content item. |
GET | /:contentId/:contentType | Get all engagements for a specific content item (paginated). |
Sources: apps/backend/src/social-engagement-module/social-engagement/social-engagement.controller.ts:37-167