Skip to content

Commit

Permalink
feat(cron): cron service for tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
sanriodev committed Apr 8, 2024
1 parent 5a9d247 commit fb7f5c0
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 13 deletions.
Binary file added bun.lockb
Binary file not shown.
12 changes: 12 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"joi": "^17.10.2",
"mongoose": "^8.0.1",
"ngrok": "^5.0.0-beta.2",
"node-cron": "^3.0.3",
"node-fetch": "^3.3.2",
"rimraf": "^5.0.1",
"source-map-support": "^0.5.21",
Expand Down
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CommandModule } from './modules/command/command.module';
import { EventModule } from './modules/event/event.module';
import { DeployModule } from './deployment/deploy.module';
import { MongoDatabaseProviderModule } from './config/database/mongo/provider/mongo-provider.module';
import { TaskModule } from './modules/cron-tasks/task.module';

@Module({
imports: [
Expand All @@ -14,6 +15,7 @@ import { MongoDatabaseProviderModule } from './config/database/mongo/provider/mo
DeployModule,
EventModule,
MongoDatabaseProviderModule,
TaskModule
],
})
export class AppModule {}
31 changes: 20 additions & 11 deletions src/modules/birthday/service/birthday-entry.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,25 @@ export class BirthdayEntryService {
}

async getEntryForToday(): Promise<BirthdayEntryDocument[]> {
const today = new Date();
const day = today.getDate();
const month = today.getMonth() + 1;
return await this.birthdayEntry.find({
$expr: {
$and: [
{ $eq: [{ $dayOfMonth: '$birthDate' }, day] },
{ $eq: [{ $month: '$birthDate' }, month] },
],
},
});
try {
let entries = await this.birthdayEntry.find<BirthdayEntryDocument>({ active: true });
if (!entries) {
return null
}

let today = new Date()

return entries
.filter((entry) => {
let date = new Date(entry.birthDate)
return (
date.getFullYear() !== today.getFullYear() &&
date.getMonth() === today.getMonth() &&
date.getDate() === today.getDate()
)
})
} catch (e) {
return null;
}
}
}
55 changes: 55 additions & 0 deletions src/modules/cron-tasks/cron-scheduler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Client, TextChannel } from 'discord.js'
import { ITask } from './tasks/interfaces/task.interface'
import BirthdayShoutoutTask from './tasks/birthday-shoutout.task'
import * as cron from 'node-cron'
import { Inject } from '@nestjs/common'
import { BirthdayEntryService } from '../birthday/service/birthday-entry.service'


interface TaskEntry {
name: string
schedule: string
task: ITask
}

class CronScheduler {
private static instance: CronScheduler
private client: Client
private tasks: TaskEntry[]

constructor(client: Client, @Inject(BirthdayEntryService) private readonly birthdayService?: BirthdayEntryService) {
if (CronScheduler.instance) {
throw new Error(`ERROR: An instance has already been created.`)
}
this.client = client
this.tasks = [
{
name: 'birthday-shoutout',
schedule: '0 10 * * *',
task: new BirthdayShoutoutTask(
this.client.channels.cache.find((channel) => channel.id === '447554141724737548') as TextChannel,birthdayService
),
},
]

CronScheduler.instance = this
}

static getInstance(): CronScheduler {
return CronScheduler.instance
}

registerTasks(): void {
this.tasks.forEach((task) => {
if (!cron.validate(task.schedule)) {
throw new Error(`ERROR: Invalid cron schedule expression for task '${task.name}'`)
}

cron.schedule(task.schedule, async () => {
await task.task.execute()
}).start()
})
}
}

export { CronScheduler }
14 changes: 14 additions & 0 deletions src/modules/cron-tasks/task.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Module } from "@nestjs/common";
import { BirthdayEntryModule } from "../birthday/module/birthday-entry.module";
import BirthdayShoutoutTask from "./tasks/birthday-shoutout.task";
import { CronScheduler } from "./cron-scheduler";


@Module({
imports: [
BirthdayEntryModule,
],
providers: [],
exports: [],
})
export class TaskModule {}
35 changes: 35 additions & 0 deletions src/modules/cron-tasks/tasks/birthday-shoutout.task.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { EmbedBuilder, TextChannel } from 'discord.js'
import { ITask } from './interfaces/task.interface'
import { BirthdayEntryService } from '../../birthday/service/birthday-entry.service'

export default class BirthdayShoutoutTask implements ITask {
private channel: TextChannel

constructor(channel: TextChannel, private readonly birthdayService: BirthdayEntryService) {
this.channel = channel
}

async execute(): Promise<void> {
let birthDayEntries = await this.birthdayService.getEntryForToday()

if (!birthDayEntries || birthDayEntries.length < 1) {
return
}

birthDayEntries.forEach((entry) => {
let creator = this.channel.members.find((member) => member.user.username === entry.username || member.user.displayName === entry.secName)

let embed = new EmbedBuilder()
.setTitle(`🚨 Birthday Alert!! 🚨`)
.setColor('Random')
.setDescription(`${entry.username ?? entry.secName} is turning **${new Date().getFullYear() - entry.birthDate.getFullYear()}** years old today! 🎉🎂🎈`)
.setFooter({
text: creator?.user.username ?? 'bingus',
iconURL: creator?.displayAvatarURL() ?? undefined,
})
.setTimestamp(new Date())

this.channel.send({ embeds: [embed] })
})
}
}
6 changes: 6 additions & 0 deletions src/modules/cron-tasks/tasks/interfaces/task.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

interface ITask {
execute(...args: any): Promise<void>
}

export type { ITask }
3 changes: 2 additions & 1 deletion src/modules/discord/discord.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Module } from '@nestjs/common';
import { DiscordService } from './discord.service';
import { AppConfigModule } from '../../config/config.module';
import { BirthdayEntryModule } from '../birthday/module/birthday-entry.module';

@Module({
imports: [AppConfigModule],
imports: [AppConfigModule, BirthdayEntryModule],
providers: [DiscordService],
exports: [DiscordService],
})
Expand Down
9 changes: 8 additions & 1 deletion src/modules/discord/discord.service.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Injectable } from '@nestjs/common';
import { Client, GatewayIntentBits } from 'discord.js';
import { AppConfigService } from '../../config/config.service';
import { CronScheduler } from '../cron-tasks/cron-scheduler';
import { BirthdayEntryService } from '../birthday/service/birthday-entry.service';

@Injectable()
export class DiscordService {
public readonly client: Client<boolean>;
public cronScheduler: CronScheduler;

constructor(configService: AppConfigService) {
constructor(configService: AppConfigService, private readonly birthdayService: BirthdayEntryService) {
this.client = new Client({
intents: [
GatewayIntentBits.Guilds,
Expand All @@ -16,5 +19,9 @@ export class DiscordService {
});

this.client.login(configService.botToken);
this.client.on('ready', () => {
this.cronScheduler = new CronScheduler(this.client, birthdayService);
this.cronScheduler.registerTasks();
});
}
}

0 comments on commit fb7f5c0

Please sign in to comment.