Skip to content

Commit 82de1ff

Browse files
Add reddit module with messages/posts controllers and shared RedditService
Co-authored-by: digitalnomad91 <2067771+digitalnomad91@users.noreply.github.com>
1 parent 0fcdc35 commit 82de1ff

11 files changed

Lines changed: 453 additions & 126 deletions

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,7 @@ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
5959
google-service-account-key.json
6060
google-services.json
6161

62-
bak/
62+
bak/
63+
64+
# npm lock file (project uses pnpm)
65+
package-lock.json

src/app-router.module.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { CloudflareKvModule } from './cloudflare-kv/cloudflare-kv.module';
44
import { WssModule } from './wss/wss.module';
55
import { JobModule } from './jobs/job.module';
66
import { AuthModule } from './auth/auth.module';
7+
import { RedditModule } from './reddit/reddit.module';
78

89
@Module({
910
imports: [
@@ -12,23 +13,11 @@ import { AuthModule } from './auth/auth.module';
1213
path: 'ws',
1314
module: WssModule,
1415
},
15-
// {
16-
// path: 'api',
17-
// children: [
18-
// {
19-
// path: '', // Empty path here - the controller already has 'jobs' path
20-
// module: JobModule,
21-
// },
22-
// {
23-
// path: '', // Empty path here - the controller already has 'auth' path
24-
// module: AuthModule,
25-
// },
26-
// ],
27-
// },
2816
]),
2917
CloudflareKvModule,
3018
JobModule,
3119
AuthModule,
20+
RedditModule,
3221
],
3322
exports: [RouterModule],
3423
})

src/jobs/job.controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {UserEntity as User} from '../common/decorators/user.decorator';
1212
//import { ApiPaginationQuery } from './../common/decorators/api-nested-query.decorator';
1313
import {PaginationArgs} from '../common/pagination/pagination.args';
1414
import {Web3CareerService} from './web3career.service';
15-
import {RedditService} from './reddit.service';
15+
import {RedditService} from '../reddit/reddit.service';
1616
import {NotificationsService} from '@/notifications/notifications.service';
1717
import {PaginatedResponse} from '../common/models/paginated-response';
1818
import {CreateJobDto as JobDto} from './dto/create-job.dto';

src/jobs/job.module.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { Module } from '@nestjs/common';
1+
import { Module, forwardRef } from '@nestjs/common';
22
import { JobService } from './job.service';
33
import { JobController } from './job.controller';
44
import { CommonModule } from '../common/common.module';
55
import { Web3CareerService } from './web3career.service';
6-
import { RedditService } from './reddit.service';
6+
import { RedditModule } from '../reddit/reddit.module';
77
// Notifications are now provided globally by NotificationsModule
88

99
/**
@@ -21,9 +21,10 @@ import { RedditService } from './reddit.service';
2121
@Module({
2222
imports: [
2323
CommonModule, // Provides database, authentication, and other shared services
24+
forwardRef(() => RedditModule), // Shared Reddit service (avoids circular dependency)
2425
],
2526
controllers: [JobController], // REST API endpoints
26-
providers: [JobService, Web3CareerService, RedditService], // Business logic
27-
exports: [JobService, Web3CareerService, RedditService], // Allow other modules to use these services
27+
providers: [JobService, Web3CareerService], // Business logic
28+
exports: [JobService, Web3CareerService], // Allow other modules to use these services
2829
})
2930
export class JobModule {}

src/jobs/reddit.service.ts

Lines changed: 0 additions & 107 deletions
This file was deleted.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import {Controller, Get, Param, ParseIntPipe, Put, Query} from '@nestjs/common';
2+
import {ApiTags} from '@nestjs/swagger';
3+
import {Api} from '@/common/decorators/api.decorator';
4+
import {MessagesService} from './messages.service';
5+
import {RedditService} from '../reddit.service';
6+
import {PaginationArgs} from '../../common/pagination/pagination.args';
7+
8+
@ApiTags('reddit')
9+
@Controller('reddit/messages')
10+
export class MessagesController {
11+
constructor(
12+
private readonly messagesService: MessagesService,
13+
private readonly redditService: RedditService
14+
) {}
15+
16+
/**
17+
* Returns a paginated table of all Reddit messages stored in the database.
18+
*/
19+
@Get()
20+
@Api({
21+
summary: 'List Reddit messages',
22+
description: 'Returns a paginated list of Reddit messages (DMs, comments) stored in the database.',
23+
queriesFrom: PaginationArgs,
24+
envelope: true,
25+
responses: [
26+
{status: 200, description: 'Messages retrieved successfully.'},
27+
],
28+
})
29+
async findAll(
30+
@Query() paginationArgs: PaginationArgs,
31+
@Query('isRead') isRead?: string,
32+
@Query('type') type?: string,
33+
@Query('subreddit') subreddit?: string
34+
) {
35+
const filter: {isRead?: boolean; type?: string; subreddit?: string} = {};
36+
if (isRead !== undefined) filter.isRead = isRead === 'true';
37+
if (type) filter.type = type;
38+
if (subreddit) filter.subreddit = subreddit;
39+
return this.messagesService.findAll(paginationArgs, filter);
40+
}
41+
42+
/**
43+
* Triggers a Reddit inbox check and stores any new messages in the database.
44+
*/
45+
@Get('check')
46+
@Api({
47+
summary: 'Check Reddit inbox for new messages',
48+
description: 'Connects to Reddit, fetches inbox messages and stores any new ones in the database.',
49+
envelope: true,
50+
responses: [
51+
{status: 200, description: 'Inbox checked and new messages stored.'},
52+
],
53+
})
54+
async checkInbox() {
55+
const newMessages = await this.redditService.checkRedditMessages();
56+
return {count: newMessages.length, messages: newMessages};
57+
}
58+
59+
/**
60+
* Returns a single Reddit message by ID.
61+
*/
62+
@Get(':id')
63+
@Api({
64+
summary: 'Get Reddit message by ID',
65+
description: 'Returns a single Reddit message stored in the database.',
66+
responses: [
67+
{status: 200, description: 'Message retrieved successfully.'},
68+
{status: 404, description: 'Message not found.'},
69+
],
70+
})
71+
async findOne(@Param('id', ParseIntPipe) id: number) {
72+
return this.messagesService.findOne(id);
73+
}
74+
75+
/**
76+
* Marks a Reddit message as read.
77+
*/
78+
@Put(':id/read')
79+
@Api({
80+
summary: 'Mark message as read',
81+
description: 'Marks a Reddit message as read in the database.',
82+
responses: [
83+
{status: 200, description: 'Message marked as read.'},
84+
{status: 404, description: 'Message not found.'},
85+
],
86+
})
87+
async markAsRead(@Param('id', ParseIntPipe) id: number) {
88+
return this.messagesService.markAsRead(id);
89+
}
90+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import {Injectable, NotFoundException} from '@nestjs/common';
2+
import {DatabaseService} from '../../common/database/database.service';
3+
import {PaginationArgs} from '../../common/pagination/pagination.args';
4+
import {buildPaginatedResult} from '../../common/pagination/pagination.util';
5+
6+
@Injectable()
7+
export class MessagesService {
8+
constructor(private readonly db: DatabaseService) {}
9+
10+
/**
11+
* Returns a paginated list of Reddit messages stored in the database.
12+
*/
13+
async findAll(paginationArgs: PaginationArgs, filter?: {isRead?: boolean; type?: string; subreddit?: string}) {
14+
const where: any = {};
15+
16+
if (filter?.isRead !== undefined) {
17+
where.isRead = filter.isRead;
18+
}
19+
if (filter?.type) {
20+
where.type = filter.type;
21+
}
22+
if (filter?.subreddit) {
23+
where.subreddit = {contains: filter.subreddit, mode: 'insensitive'};
24+
}
25+
26+
const take = paginationArgs.first ? Number(paginationArgs.first) : 20;
27+
const skip = paginationArgs.skip ? Number(paginationArgs.skip) : 0;
28+
29+
const [messages, totalCount] = await Promise.all([
30+
this.db.redditMessage.findMany({
31+
where,
32+
orderBy: {createdAt: 'desc'},
33+
skip,
34+
take,
35+
}),
36+
this.db.redditMessage.count({where}),
37+
]);
38+
39+
return buildPaginatedResult({items: messages, skip, take, totalCount, meta: null});
40+
}
41+
42+
/**
43+
* Returns a single Reddit message by its database ID.
44+
*/
45+
async findOne(id: number) {
46+
const message = await this.db.redditMessage.findUnique({where: {id}});
47+
if (!message) {
48+
throw new NotFoundException(`Reddit message with ID ${id} not found`);
49+
}
50+
return message;
51+
}
52+
53+
/**
54+
* Marks a Reddit message as read.
55+
*/
56+
async markAsRead(id: number) {
57+
await this.findOne(id);
58+
return this.db.redditMessage.update({
59+
where: {id},
60+
data: {isRead: true},
61+
});
62+
}
63+
}

0 commit comments

Comments
 (0)